@@ -0,0 +1,156 @@
// 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 dns = require('dns');
var fs = require('fs');
var net = require('net');

var errorMsgs = [];
var caught = 0;
var expectCaught = 0;
var exitCbRan = false;

function asyncL() { }

var callbacksObj = {
error: function(value, er) {
var idx = errorMsgs.indexOf(er.message);

caught++;

if (-1 < idx)
errorMsgs.splice(idx, 1);
else
throw new Error('Message not found: ' + er.message);

return true;
}
};

var listener = process.createAsyncListener(asyncL, callbacksObj);

process.on('exit', function(code) {
// Just in case.
process.removeAsyncListener(listener);

if (code > 0)
return;

assert.ok(!exitCbRan);
exitCbRan = true;

if (errorMsgs.length > 0)
throw new Error('Errors not fired: ' + errorMsgs);

assert.equal(caught, expectCaught);
process._rawDebug('ok');
});


// Simple cases
errorMsgs.push('setTimeout - simple');
errorMsgs.push('setImmediate - simple');
errorMsgs.push('setInterval - simple');
setTimeout(function() {
throw new Error('setTimeout - simple');
}).addAsyncListener(listener);
expectCaught++;

setImmediate(function() {
throw new Error('setImmediate - simple');
}).addAsyncListener(listener);
expectCaught++;

var b = setInterval(function() {
clearInterval(b);
throw new Error('setInterval - simple');
}).addAsyncListener(listener);
expectCaught++;


// Deeply nested
errorMsgs.push('setInterval - nested');
errorMsgs.push('setImmediate - nested');
errorMsgs.push('setTimeout - nested');
setTimeout(function() {
setImmediate(function() {
var b = setInterval(function() {
clearInterval(b);
throw new Error('setInterval - nested');
}).addAsyncListener(listener);
expectCaught++;
throw new Error('setImmediate - nested');
}).addAsyncListener(listener);
expectCaught++;
throw new Error('setTimeout - nested');
}).addAsyncListener(listener);
expectCaught++;


// Net
var iter = 3;
for (var i = 0; i < iter; i++) {
errorMsgs.push('net - server connection');
errorMsgs.push('net - client data');
errorMsgs.push('net - server data');
}
errorMsgs.push('net - server closed');

var server = net.createServer(function(c) {
c._handle.addAsyncListener(listener);

c.on('data', function() {
if (0 === --iter) {
server.close(function() {
throw new Error('net - server closed');
});
expectCaught++;
}
throw new Error('net - server data');
});
expectCaught++;

c.end('bye');
throw new Error('net - server connection');
});
expectCaught += iter;

server.listen(common.PORT, function() {
// Test adding the async listener after server creation. Though it
// won't catch errors that originate synchronously from this point.
server._handle.addAsyncListener(listener);
for (var i = 0; i < iter; i++)
clientConnect();
});

function clientConnect() {
var client = net.connect(common.PORT, function() {
client._handle.addAsyncListener(listener);
});

client.on('data', function() {
client.end('see ya');
throw new Error('net - client data');
});
expectCaught++;
}
@@ -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');
});
@@ -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');
});
@@ -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');
});
@@ -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');
});
@@ -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');
});

@@ -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');
});
@@ -0,0 +1,78 @@
// 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 childStr = '';
var child = spawn(process.execPath, [__filename, 'child']);
child.stderr.on('data', function(chunk) {
childStr += chunk.toString();
});

child.on('exit', function(code) {
// This is thrown when Node throws from _fatalException.
assert.equal(code, 7);
});

process.on('exit', function() {
assert.notEqual(childStr.indexOf(checkStr), -1);
console.log('ok');
});
}

@@ -0,0 +1,258 @@
// 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 dns = require('dns');
var fs = require('fs');
var net = require('net');

var addListener = process.addAsyncListener;
var removeListener = process.removeAsyncListener;
var errorMsgs = [];
var currentMsg = '';
var caught = 0;
var expectCaught = 0;
var exitCbRan = false;

function asyncL() { }

var callbacksObj = {
error: function(value, er) {
var idx = errorMsgs.indexOf(er.message);

caught++;

if (-1 < idx)
errorMsgs.splice(idx, 1);

return currentMsg === er.message;
}
};

var listener = process.createAsyncListener(asyncL, callbacksObj);

process.on('exit', function(code) {
removeListener(listener);

// Something else went wrong, no need to further check.
if (code > 0)
return;

// Make sure the exit callback only runs once.
assert.ok(!exitCbRan);
exitCbRan = true;

// Check if any error messages weren't removed from the msg queue.
if (errorMsgs.length > 0)
throw new Error('Errors not fired: ' + errorMsgs);

assert.equal(caught, expectCaught, 'caught all expected errors');
process._rawDebug('ok');
});


// Catch synchronous throws
errorMsgs.push('sync throw');
process.nextTick(function() {
addListener(listener);

expectCaught++;
currentMsg = 'sync throw';
throw new Error(currentMsg);

removeListener(listener);
});


// Simple cases
errorMsgs.push('setTimeout - simple');
errorMsgs.push('setImmediate - simple');
errorMsgs.push('setInterval - simple');
errorMsgs.push('process.nextTick - simple');
process.nextTick(function() {
addListener(listener);

setTimeout(function() {
currentMsg = 'setTimeout - simple';
throw new Error(currentMsg);
});
expectCaught++;

setImmediate(function() {
currentMsg = 'setImmediate - simple';
throw new Error(currentMsg);
});
expectCaught++;

var b = setInterval(function() {
clearInterval(b);
currentMsg = 'setInterval - simple';
throw new Error(currentMsg);
});
expectCaught++;

process.nextTick(function() {
currentMsg = 'process.nextTick - simple';
throw new Error(currentMsg);
});
expectCaught++;

removeListener(listener);
});


// Deeply nested
errorMsgs.push('setInterval - nested');
errorMsgs.push('setImmediate - nested');
errorMsgs.push('process.nextTick - nested');
errorMsgs.push('setTimeout2 - nested');
errorMsgs.push('setTimeout - nested');
process.nextTick(function() {
addListener(listener);

setTimeout(function() {
process.nextTick(function() {
setImmediate(function() {
var b = setInterval(function() {
clearInterval(b);
currentMsg = 'setInterval - nested';
throw new Error(currentMsg);
});
expectCaught++;
currentMsg = 'setImmediate - nested';
throw new Error(currentMsg);
});
expectCaught++;
currentMsg = 'process.nextTick - nested';
throw new Error(currentMsg);
});
expectCaught++;
setTimeout(function() {
currentMsg = 'setTimeout2 - nested';
throw new Error(currentMsg);
});
expectCaught++;
currentMsg = 'setTimeout - nested';
throw new Error(currentMsg);
});
expectCaught++;

removeListener(listener);
});


// FS
errorMsgs.push('fs - file does not exist');
errorMsgs.push('fs - exists');
errorMsgs.push('fs - realpath');
process.nextTick(function() {
addListener(listener);

fs.stat('does not exist', function(err, stats) {
currentMsg = 'fs - file does not exist';
throw new Error(currentMsg);
});
expectCaught++;

fs.exists('hi all', function(exists) {
currentMsg = 'fs - exists';
throw new Error(currentMsg);
});
expectCaught++;

fs.realpath('/some/path', function(err, resolved) {
currentMsg = 'fs - realpath';
throw new Error(currentMsg);
});
expectCaught++;

removeListener(listener);
});


// Nested FS
errorMsgs.push('fs - nested file does not exist');
process.nextTick(function() {
addListener(listener);

setTimeout(function() {
setImmediate(function() {
var b = setInterval(function() {
clearInterval(b);
process.nextTick(function() {
fs.stat('does not exist', function(err, stats) {
currentMsg = 'fs - nested file does not exist';
throw new Error(currentMsg);
});
expectCaught++;
});
});
});
});

removeListener(listener);
});


// Net
errorMsgs.push('net - connection listener');
errorMsgs.push('net - client connect');
errorMsgs.push('net - server listening');
process.nextTick(function() {
addListener(listener);

var server = net.createServer(function(c) {
server.close();
currentMsg = 'net - connection listener';
throw new Error(currentMsg);
});
expectCaught++;

server.listen(common.PORT, function() {
var client = net.connect(common.PORT, function() {
client.end();
currentMsg = 'net - client connect';
throw new Error(currentMsg);
});
expectCaught++;
currentMsg = 'net - server listening';
throw new Error(currentMsg);
});
expectCaught++;

removeListener(listener);
});


// DNS
errorMsgs.push('dns - lookup');
process.nextTick(function() {
addListener(listener);

dns.lookup('localhost', function() {
currentMsg = 'dns - lookup';
throw new Error(currentMsg);
});
expectCaught++;

removeListener(listener);
});
@@ -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');

var addListener = process.addAsyncListener;
var removeListener = process.removeAsyncListener;
var caught = [];
var expect = [];

function asyncL(a) {}

var callbacksObj = {
error: function(value, er) {
process._rawDebug('caught', er.message);
caught.push(er.message);
return (expect.indexOf(er.message) !== -1);
}
};

var listener = process.createAsyncListener(asyncL, callbacksObj);

process.on('exit', function(code) {
removeListener(listener);

if (code > 0)
return;

expect = expect.sort();
caught = caught.sort();

process._rawDebug('expect', expect);
process._rawDebug('caught', caught);
assert.deepEqual(caught, expect, 'caught all expected errors');
process._rawDebug('ok');
});


expect.push('immediate simple a');
expect.push('immediate simple b');
process.nextTick(function() {
addListener(listener);
// Tests for a setImmediate specific bug encountered while implementing
// AsyncListeners.
setImmediate(function() {
throw new Error('immediate simple a');
});
setImmediate(function() {
throw new Error('immediate simple b');
});
removeListener(listener);
});
@@ -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');
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. Though currently there's
// no way to do that.
var listener = process.addAsyncListener(function() { });


// Test timers

setImmediate(function() {
assert.equal(this._asyncQueue.length, 0);
}).removeAsyncListener(listener);

setTimeout(function() {
assert.equal(this._asyncQueue.length, 0);
}).removeAsyncListener(listener);

setInterval(function() {
clearInterval(this);
assert.equal(this._asyncQueue.length, 0);
}).removeAsyncListener(listener);


// Test net

var server = net.createServer(function(c) {
c._handle.removeAsyncListener(listener);
assert.equal(c._handle._asyncQueue.length, 0);
});

server.listen(common.PORT, function() {
server._handle.removeAsyncListener(listener);
assert.equal(server._handle._asyncQueue.length, 0);

var client = net.connect(common.PORT, function() {
client._handle.removeAsyncListener(listener);
assert.equal(client._handle._asyncQueue.length, 0);
client.end();
server.close();
});
});
@@ -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');
});


@@ -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');
});
@@ -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');
});

@@ -0,0 +1,47 @@
// 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');

// If there is an uncaughtException listener then the error thrown from
// "before" will be considered handled, thus calling setImmediate to
// finish execution of the nextTickQueue. This in turn will cause "before"
// to fire again, entering into an infinite loop.
// So the asyncQueue is cleared from the returned setImmediate in
// _fatalException to prevent this from happening.
var cntr = 0;


process.addAsyncListener(function() { }, {
before: function() {
if (++cntr > 1) {
// Can't throw since uncaughtException will also catch that.
process._rawDebug('Error: Multiple before callbacks called');
process.exit(1);
}
throw new Error('before');
}
});

process.on('uncaughtException', function() { });

process.nextTick();
@@ -0,0 +1,185 @@
// 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 net = require('net');
var fs = require('fs');
var dgram = require('dgram');

var addListener = process.addAsyncListener;
var removeListener = process.removeAsyncListener;
var actualAsync = 0;
var expectAsync = 0;

function onAsync() {
actualAsync++;
}

var listener = process.createAsyncListener(onAsync);

process.on('exit', function() {
process._rawDebug('expected', expectAsync);
process._rawDebug('actual ', actualAsync);
// TODO(trevnorris): Not a great test. If one was missed, but others
// overflowed then the test would still pass.
assert.ok(actualAsync >= expectAsync);
});


// Test listeners side-by-side
process.nextTick(function() {
addListener(listener);

var b = setInterval(function() {
clearInterval(b);
});
expectAsync++;

var c = setInterval(function() {
clearInterval(c);
});
expectAsync++;

setTimeout(function() { });
expectAsync++;

setTimeout(function() { });
expectAsync++;

process.nextTick(function() { });
expectAsync++;

process.nextTick(function() { });
expectAsync++;

setImmediate(function() { });
expectAsync++;

setImmediate(function() { });
expectAsync++;

setTimeout(function() { }, 10);
expectAsync++;

setTimeout(function() { }, 10);
expectAsync++;

removeListener(listener);
});


// Async listeners should propagate with nested callbacks
process.nextTick(function() {
addListener(listener);
var interval = 3;

process.nextTick(function() {
setTimeout(function() {
setImmediate(function() {
var i = setInterval(function() {
if (--interval <= 0)
clearInterval(i);
});
expectAsync++;
});
expectAsync++;
process.nextTick(function() {
setImmediate(function() {
setTimeout(function() { }, 20);
expectAsync++;
});
expectAsync++;
});
expectAsync++;
});
expectAsync++;
});
expectAsync++;

removeListener(listener);
});


// Test triggers with two async listeners
process.nextTick(function() {
addListener(listener);
addListener(listener);

setTimeout(function() {
process.nextTick(function() { });
expectAsync += 2;
});
expectAsync += 2;

removeListener(listener);
removeListener(listener);
});


// Test callbacks from fs I/O
process.nextTick(function() {
addListener(listener);

fs.stat('something random', function(err, stat) { });
expectAsync++;

setImmediate(function() {
fs.stat('random again', function(err, stat) { });
expectAsync++;
});
expectAsync++;

removeListener(listener);
});


// Test net I/O
process.nextTick(function() {
addListener(listener);

var server = net.createServer(function(c) { });
expectAsync++;

server.listen(common.PORT, function() {
server.close();
expectAsync++;
});
expectAsync++;

removeListener(listener);
});


// Test UDP
process.nextTick(function() {
addListener(listener);

var server = dgram.createSocket('udp4');
expectAsync++;

server.bind(common.PORT);

server.close();
expectAsync++;

removeListener(listener);
});
@@ -1005,3 +1005,6 @@ assert.throws(function() {
assert.throws(function() {
crypto.createVerify('RSA-SHA1').update('0', 'hex');
}, /Bad input string/);

// Make sure memory isn't released before being returned
console.log(crypto.randomBytes(16));
@@ -45,11 +45,10 @@ var server = http.createServer(function(req, res) {
res.end(er.stack || er.message || 'Unknown error');
});

var data;
dom.run(function() {
// Now, an action that has the potential to fail!
// if you request 'baz', then it'll throw a JSON circular ref error.
data = JSON.stringify(objects[req.url.replace(/[^a-z]/g, '')]);
var data = JSON.stringify(objects[req.url.replace(/[^a-z]/g, '')]);

// this line will throw if you pick an unknown key
assert(data !== undefined, 'Data should not be undefined');
@@ -64,8 +63,6 @@ server.listen(common.PORT, next);
function next() {
console.log('listening on localhost:%d', common.PORT);

// now hit it a few times
var dom = domain.create();
var requests = 0;
var responses = 0;

@@ -31,12 +31,12 @@ var e = new events.EventEmitter();
var d = domain.create();
d.add(e);
d.on('error', function (er) {
assert(er instanceof TypeError, 'type error created');
assert(er instanceof Error, 'error created');
errorCatched = true;
});

e.emit('error');

process.on('exit', function () {
assert(errorCatched, 'error got catched');
assert(errorCatched, 'error got caught');
});
@@ -50,6 +50,7 @@ var server = tls.createServer(options, function(socket) {
function unauthorized() {
var socket = tls.connect({
port: common.PORT,
servername: 'localhost',
rejectUnauthorized: false
}, function() {
assert(!socket.authorized);
@@ -63,7 +64,9 @@ function unauthorized() {
}

function rejectUnauthorized() {
var socket = tls.connect(common.PORT, function() {
var socket = tls.connect(common.PORT, {
servername: 'localhost'
}, function() {
assert(false);
});
socket.on('error', function(err) {
@@ -75,7 +78,8 @@ function rejectUnauthorized() {

function authorized() {
var socket = tls.connect(common.PORT, {
ca: [fs.readFileSync(path.join(common.fixturesDir, 'test_cert.pem'))]
ca: [fs.readFileSync(path.join(common.fixturesDir, 'test_cert.pem'))],
servername: 'localhost'
}, function() {
assert(socket.authorized);
socket.end();