blob: 78f91ad6851cdfdeadb85476ab881f1194980cb3 [file] [log] [blame]
/**
* Forge XmlHttpRequest Test
*
* @author Dave Longley
* @author David I. Lehn <dlehn@digitalbazaar.com>
*
* Copyright (c) 2009-2010 Digital Bazaar, Inc. All rights reserved.
*/
(function($)
{
// load flash socket pool
window.forge.socketPool = {};
window.forge.socketPool.ready = function()
{
// init forge xhr
forge.xhr.init({
flashId: 'socketPool',
policyPort: 19945,
msie: $.browser.msie,
connections: 10,
caCerts: [],
verify: function(c, verified, depth, certs)
{
// don't care about cert verification for test
return true;
}
});
};
swfobject.embedSWF(
'forge/SocketPool.swf', 'socketPool', '0', '0', '9.0.0',
false, {}, {allowscriptaccess: 'always'}, {});
})(jQuery);
jQuery(function($)
{
var cat = 'forge.tests.xhr';
var tests = [];
var passed = 0;
var failed = 0;
var init = function() {
passed = failed = 0;
$('.ready,.testing,.pass,.fail')
.removeClass('ready testing pass fail');
$('#status')
.text('Ready.')
.addClass('ready');
$('#total').text(tests.length);
$('#pass').text(passed);
$('#fail').text(failed);
$('.expect').empty();
$('.result').empty();
$('.time').empty();
$('.timePer').empty();
$('#start').removeAttr('disabled');
};
var start = function()
{
$('#start').attr('disabled', 'disabled');
// meta! use tasks to run the task tests
forge.task.start({
type: 'test',
run: function(task) {
task.next('starting', function(task) {
forge.log.debug(cat, 'start');
$('#status')
.text('Testing...')
.addClass('testing')
.removeClass('idle');
});
$.each(tests, function(i, test) {
task.next('test', function(task) {
var title = $('li:first', test.container);
if($('#scroll:checked').length === 1)
{
$('html,body').animate({scrollTop: title.offset().top});
}
title.addClass('testing');
test.run(task, test);
});
task.next('test', function(task) {
$('li:first', test.container).removeClass('testing');
});
});
task.next('success', function(task) {
forge.log.debug(cat, 'done');
if(failed === 0) {
$('#status')
.text('PASS')
.addClass('pass')
.removeClass('testing');
} else {
// FIXME: should just be hitting failure() below
$('#status')
.text('FAIL')
.addClass('fail')
.removeClass('testing');
}
});
},
failure: function() {
$('#status')
.text('FAIL')
.addClass('fail')
.removeClass('testing');
}
});
};
$('#start').click(function() {
start();
});
$('#reset').click(function() {
init();
});
var stressStats =
{
sent: 0,
success: 0,
error: 0
};
var stressStatsMessage = function()
{
return 'received:' + (stressStats.success + stressStats.error) + '/' +
stressStats.sent + ' errors:' + stressStats.error;
};
$('#stress').click(function() {
for(var i = 1; i <= 100; ++i)
{
(function(seqnum)
{
setTimeout(function()
{
$.ajax(
{
type: 'GET',
url: '/result.txt?seq=' + seqnum,
beforeSend: function(xhr)
{
++stressStats.sent;
xhr.setRequestHeader('Connection', 'close');
},
success: function(data, textStatus, xhr)
{
++stressStats.success;
forge.log.debug(cat, 'xhr connection completed' +
' seq:' + seqnum +
' datalen:' + data.length + ' ' +
stressStatsMessage());
},
error: function(xhr, textStatus, errorThrown)
{
++stressStats.error;
forge.log.error(cat, 'xhr connection failed' +
' seq:' + seqnum + ' ' +
stressStatsMessage(), arguments);
},
xhr: forge.xhr.create
});
}, 0);
})(i);
}
return false;
});
/**
* Creates a simple XMLHttpRequest wrapper. For testing.
*/
var createWrapper = function()
{
var UNSENT = 0;
var OPENED = 1;
var HEADERS_RECEIVED = 2;
var LOADING = 3;
var DONE = 4;
var toWrap = new XMLHttpRequest();
// create xhr wrapper object
var xhr =
{
// FIXME: an EventListener
onreadystatechange: null,
// FIXME: readonly
readyState: UNSENT,
// FIXME: a string
responseText: null,
// FIXME: a document
responseXML: null,
// FIXME: readonly, returns the HTTP status code
status: 0,
// FIXME: readonly, returns the HTTP status message
statusText: null,
// FIXME: async, user, and password are optional
open: function(method, url, async, user, password)
{
toWrap.open(method, url, async, user, password);
},
setRequestHeader: function(header, value)
{
toWrap.setRequestHeader(header, value);
},
// FIXME: data can be a string or a document
send: function(data)
{
toWrap.send(data);
},
abort: function()
{
toWrap.abort();
toWrap.onreadystatechange = null;
toWrap = null;
},
// FIXME: return all response headers as a string
getAllResponseHeaders: function()
{
return toWrap.getAllResponseHeaders();
},
// FIXME: return header field value
getResponseHeader: function(header)
{
return toWrap.getResponseHeader(header);
}
};
toWrap.onreadystatechange = function()
{
// copy attributes
xhr.readyState = toWrap.readyState;
xhr.responseText = toWrap.responseText;
xhr.responseXML = toWrap.responseXML;
if(toWrap.readyState == HEADERS_RECEIVED)
{
xhr.status = toWrap.status;
xhr.statusText = toWrap.statusText;
}
if(xhr.onreadystatechange)
{
//forge.log.debug(cat, 'wrapper orsc', toWrap);
xhr.onreadystatechange();
}
};
return xhr;
};
var addTest = function(name, run)
{
var container = $('<ul><li>Test ' + name + '</li><ul/></ul>');
var expect = $('<li>Expect: <span class="expect"/></li>');
var result = $('<li>Result: <span class="result"/></li>');
var time = $('<li>Time: <span class="time"/></li>');
var timePer = $('<li>Time Per Iteration: <span class="timePer"/></li>');
$('ul', container)
.append(expect)
.append(result)
.append(time)
.append(timePer);
$('#tests').append(container);
var test = {
container: container,
startTime: null,
run: function(task, test) {
test.startTime = new Date();
run(task, test);
},
expect: $('span', expect),
result: $('span', result),
check: function() {
var e = test.expect.text();
var r = test.result.text();
(e == r) ? test.pass() : test.fail();
},
pass: function(iterations) {
var dt = new Date() - test.startTime;
if(!iterations)
{
iterations = 1;
}
var dti = (dt / iterations);
passed += 1;
$('#pass').text(passed);
$('li:first', container).addClass('pass');
$('span.time', container).html(dt + 'ms');
$('span.timePer', container).html(dti + 'ms');
},
fail: function(iterations) {
var dt = new Date() - test.startTime;
if(!iterations)
{
iterations = 1;
}
var dti = (dt / iterations);
failed += 1;
$('#fail').text(failed);
$('li:first', container).addClass('fail');
$('span.time', container).html(dt + 'ms');
$('span.timePer', container).html(dti + 'ms');
}
};
tests.push(test);
};
addTest('builtin xhr', function(task, test)
{
task.block();
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data)
{
test.expect.html('expected result');
test.result.html(data);
task.unblock();
},
error: function()
{
task.fail();
}
});
task.next(function(task)
{
test.pass();
});
});
addTest('builtin xhr (10 serial)', function(task, test)
{
var N = 10;
for(var i = 0; i < N; i++)
{
task.next(function(task)
{
task.parent.block();
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus)
{
test.result.append('.');
task.parent.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail(N);
}
});
});
}
task.next(function(task)
{
test.pass(N);
});
});
addTest('builtin xhr (10 parallel)', function(task, test)
{
var N = 10;
task.block(N);
for(var i = 0; i < N; i++)
{
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus)
{
test.result.append('.');
task.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail(N);
}
});
}
task.next(function(task)
{
test.pass(N);
});
});
// test only works with non-IE
if(!$.browser.msie)
{
addTest('generic wrapper xhr', function(task, test)
{
task.block();
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data)
{
test.expect.html('expected result');
test.result.html(data);
task.unblock();
},
error: function()
{
task.fail();
},
xhr: createWrapper
});
task.next(function(task)
{
test.pass();
});
});
addTest('generic wrapper xhr (10 serial)', function(task, test)
{
var N = 10;
for(var i = 0; i < N; i++)
{
task.next(function(task)
{
task.parent.block();
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus)
{
test.result.append('.');
task.parent.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail(N);
},
xhr: createWrapper
});
});
}
task.next(function(task)
{
test.pass(N);
});
});
addTest('generic wrapper xhr (10 parallel)', function(task, test)
{
var N = 10;
task.block(N);
for(var i = 0; i < N; i++)
{
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus)
{
test.result.append('.');
task.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail(N);
},
xhr: createWrapper
});
}
task.next(function(task)
{
test.pass(N);
});
});
}
for(var i = 0; i < 3; i++) {
addTest('TLS xhr ' + i, function(task, test)
{
task.block();
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus, xhr)
{
test.expect.html('expected result');
test.result.html(data);
task.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail();
},
xhr: forge.xhr.create
});
task.next(function(task)
{
test.pass();
});
});
}
addTest('TLS xhr (10 serial)', function(task, test)
{
var N = 10;
for(var i = 0; i < N; i++)
{
task.next(function(task)
{
task.parent.block();
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus, xhr)
{
test.result.append('.');
task.parent.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail(N);
},
xhr: forge.xhr.create
});
});
}
task.next(function(task)
{
test.pass(N);
});
});
addTest('TLS xhr (10 parallel) ' +
'(hit "Reset" then "Start" to speed up - uses SSL session cache)',
function(task, test)
{
var N = 10;
task.block(N);
for(var i = 0; i < N; i++)
{
$.ajax(
{
type: 'GET',
url: '/result.txt',
success: function(data, textStatus, xhr)
{
test.result.append('.');
task.unblock();
},
error: function(xhr, textStatus, errorThrown)
{
task.fail(N);
},
xhr: forge.xhr.create
});
}
task.next(function(task)
{
test.pass(N);
});
});
init();
});