You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

242 lines
5.4 KiB

;(function(root) {
'use strict';
/** Use a single `load` function */
var load = typeof require == 'function' ? require : root.load;
/** The unit testing framework */
var QUnit = (function() {
var noop = Function.prototype;
return root.QUnit || (
root.addEventListener || (root.addEventListener = noop),
root.setTimeout || (root.setTimeout = noop),
root.QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit,
(load('../node_modules/qunit-clib/qunit-clib.js') || { 'runInContext': noop }).runInContext(root),
addEventListener === noop && delete root.addEventListener,
root.QUnit
);
}());
/** The `utf8` object to test */
var utf8 = root.utf8 || (root.utf8 = (
utf8 = load('../utf8.js') || root.utf8,
utf8 = utf8.utf8 || utf8
));
/*--------------------------------------------------------------------------*/
function forEach(array, fn) {
var index = -1;
var length = array.length;
while (++index < length) {
fn(array[index]);
}
}
// Quick and dirty test to see if we’re in Node & need extended tests
var runExtendedTests = (function() {
try {
return process.argv[0] == 'node' && process.argv[2] == '--extended';
} catch(error) { }
}());
var data = [
// 1-byte
{
'codePoint': 0x0000,
'decoded': '\0',
'encoded': '\0'
},
{
'codePoint': 0x005C,
'decoded': '\x5C',
'encoded': '\x5C'
},
{
'codePoint': 0x007F,
'decoded': '\x7F',
'encoded': '\x7F'
},
// 2-byte
{
'codePoint': 0x0080,
'decoded': '\x80',
'encoded': '\xC2\x80'
},
{
'codePoint': 0x05CA,
'decoded': '\u05CA',
'encoded': '\xD7\x8A'
},
{
'codePoint': 0x07FF,
'decoded': '\u07FF',
'encoded': '\xDF\xBF',
},
// 3-byte
{
'codePoint': 0x0800,
'decoded': '\u0800',
'encoded': '\xE0\xA0\x80',
},
{
'codePoint': 0x2C3C,
'decoded': '\u2C3C',
'encoded': '\xE2\xB0\xBC'
},
{
'codePoint': 0xFFFF,
'decoded': '\uFFFF',
'encoded': '\xEF\xBF\xBF'
},
// unmatched surrogate halves
// high surrogates: 0xD800 to 0xDBFF
{
'codePoint': 0xD800,
'decoded': '\uD800',
'encoded': '\xED\xA0\x80'
},
{
'description': 'High surrogate followed by another high surrogate',
'decoded': '\uD800\uD800',
'encoded': '\xED\xA0\x80\xED\xA0\x80'
},
{
'description': 'High surrogate followed by a symbol that is not a surrogate',
'decoded': '\uD800A',
'encoded': '\xED\xA0\x80A'
},
{
'description': 'Unmatched high surrogate, followed by a surrogate pair, followed by an unmatched high surrogate',
'decoded': '\uD800\uD834\uDF06\uD800',
'encoded': '\xED\xA0\x80\xF0\x9D\x8C\x86\xED\xA0\x80'
},
{
'codePoint': 0xD9AF,
'decoded': '\uD9AF',
'encoded': '\xED\xA6\xAF'
},
{
'codePoint': 0xDBFF,
'decoded': '\uDBFF',
'encoded': '\xED\xAF\xBF'
},
// low surrogates: 0xDC00 to 0xDFFF
{
'codePoint': 0xDC00,
'decoded': '\uDC00',
'encoded': '\xED\xB0\x80'
},
{
'description': 'Low surrogate followed by another low surrogate',
'decoded': '\uDC00\uDC00',
'encoded': '\xED\xB0\x80\xED\xB0\x80'
},
{
'description': 'Low surrogate followed by a symbol that is not a surrogate',
'decoded': '\uDC00A',
'encoded': '\xED\xB0\x80A'
},
{
'description': 'Unmatched low surrogate, followed by a surrogate pair, followed by an unmatched low surrogate',
'decoded': '\uDC00\uD834\uDF06\uDC00',
'encoded': '\xED\xB0\x80\xF0\x9D\x8C\x86\xED\xB0\x80'
},
{
'codePoint': 0xDEEE,
'decoded': '\uDEEE',
'encoded': '\xED\xBB\xAE'
},
{
'codePoint': 0xDFFF,
'decoded': '\uDFFF',
'encoded': '\xED\xBF\xBF'
},
// 4-byte
{
'codePoint': 0x010000,
'decoded': '\uD800\uDC00',
'encoded': '\xF0\x90\x80\x80'
},
{
'codePoint': 0x01D306,
'decoded': '\uD834\uDF06',
'encoded': '\xF0\x9D\x8C\x86'
},
{
'codePoint': 0x10FFF,
'decoded': '\uDBFF\uDFFF',
'encoded': '\xF4\x8F\xBF\xBF'
}
];
if (runExtendedTests) {
data = data.concat(require('./data.json'));
}
// `throws` is a reserved word in ES3; alias it to avoid errors
var raises = QUnit.assert['throws'];
// explicitly call `QUnit.module()` instead of `module()`
// in case we are in a CLI environment
QUnit.module('utf8.js');
test('encode/decode', function() {
forEach(data, function(object) {
var description = object.description || 'U+' + object.codePoint.toString(16).toUpperCase();
;
equal(
object.encoded,
utf8.encode(object.decoded),
'Encoding: ' + description
);
equal(
object.decoded,
utf8.decode(object.encoded),
'Decoding: ' + description
);
});
// Error handling
raises(
function() {
utf8.decode('\uFFFF');
},
Error,
'Error: invalid UTF-8 detected'
);
raises(
function() {
utf8.decode('\xE9\x00\x00');
},
Error,
'Error: invalid continuation byte (4-byte sequence expected)'
);
raises(
function() {
utf8.decode('\xC2\uFFFF');
},
Error,
'Error: invalid continuation byte'
);
raises(
function() {
utf8.decode('\xF0\x9D');
},
Error,
'Error: invalid byte index'
);
});
/*--------------------------------------------------------------------------*/
// configure QUnit and call `QUnit.start()` for
// Narwhal, Node.js, PhantomJS, Rhino, and RingoJS
if (!root.document || root.phantom) {
QUnit.config.noglobals = true;
QUnit.start();
}
}(typeof global == 'object' && global || this));