yencode 1.0.8 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +339 -231
- package/binding.gyp +292 -39
- package/crcutil-1.0/code/multiword_64_64_gcc_amd64_asm.cc +7 -7
- package/crcutil-1.0/code/multiword_64_64_gcc_i386_mmx.cc +14 -14
- package/crcutil-1.0/code/multiword_64_64_intrinsic_i386_mmx.cc +1 -1
- package/crcutil-1.0/code/uint128_sse2.h +2 -0
- package/index.js +329 -22
- package/package.json +2 -2
- package/src/common.h +299 -0
- package/src/crc.cc +95 -0
- package/src/crc.h +23 -0
- package/src/crc_arm.cc +175 -0
- package/src/crc_common.h +4 -0
- package/{crc_folding.c → src/crc_folding.cc} +175 -185
- package/src/decoder.cc +61 -0
- package/src/decoder.h +53 -0
- package/src/decoder_avx.cc +18 -0
- package/src/decoder_avx2.cc +18 -0
- package/src/decoder_avx2_base.h +615 -0
- package/src/decoder_common.h +512 -0
- package/src/decoder_neon.cc +474 -0
- package/src/decoder_neon64.cc +451 -0
- package/src/decoder_sse2.cc +16 -0
- package/src/decoder_sse_base.h +711 -0
- package/src/decoder_ssse3.cc +18 -0
- package/src/encoder.cc +170 -0
- package/src/encoder.h +21 -0
- package/src/encoder_avx.cc +16 -0
- package/src/encoder_avx2.cc +16 -0
- package/src/encoder_avx_base.h +564 -0
- package/src/encoder_common.h +109 -0
- package/src/encoder_neon.cc +547 -0
- package/src/encoder_sse2.cc +13 -0
- package/src/encoder_sse_base.h +724 -0
- package/src/encoder_ssse3.cc +18 -0
- package/src/hedley.h +1899 -0
- package/src/platform.cc +147 -0
- package/src/yencode.cc +449 -0
- package/test/_maxsize.js +9 -0
- package/test/_speedbase.js +147 -0
- package/test/speedcrc.js +20 -0
- package/test/speeddec.js +92 -0
- package/test/speedenc.js +44 -0
- package/{testcrc.js → test/testcrc.js} +53 -39
- package/test/testdec.js +183 -0
- package/test/testenc.js +163 -0
- package/test/testpostdec.js +126 -0
- package/test.js +0 -91
- package/yencode.cc +0 -1622
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// test config (defaults)
|
|
2
|
+
var sz = 768000;
|
|
3
|
+
var rounds = 80;
|
|
4
|
+
var trials = 8;
|
|
5
|
+
var asyncWait = 1000;
|
|
6
|
+
|
|
7
|
+
var maxSize = require('./_maxsize');
|
|
8
|
+
var decimal = (''+1.1).substr(1, 1);
|
|
9
|
+
var fmtSpeed = function(size, time) {
|
|
10
|
+
var rate = ('' + (Math.round(100*(size/1048576)/time)/100)).split(decimal);
|
|
11
|
+
|
|
12
|
+
return (' ' + rate[0]).substr(-8) + decimal + ((rate[1]|0) + '00').substr(0, 2) + ' MiB/s';
|
|
13
|
+
};
|
|
14
|
+
var initBuffers = function() {
|
|
15
|
+
module.exports.bufWorst = new Buffer(sz);
|
|
16
|
+
module.exports.bufBest = new Buffer(sz);
|
|
17
|
+
module.exports.bufAvg = [];
|
|
18
|
+
module.exports.bufAvg2x = [];
|
|
19
|
+
module.exports.bufTarget = new Buffer(maxSize(sz));
|
|
20
|
+
|
|
21
|
+
module.exports.bufWorst.fill(224);
|
|
22
|
+
module.exports.bufBest.fill(0);
|
|
23
|
+
|
|
24
|
+
// use cipher as a fast, consistent RNG
|
|
25
|
+
var cipher = require('crypto').createCipher;
|
|
26
|
+
[['aes-128-cbc', 'my_incredibly_strong_password'],
|
|
27
|
+
['rc4', 'my_incredibly_strong_password'],
|
|
28
|
+
['aes-128-cbc', '9h8a08b08qpklnac']
|
|
29
|
+
].forEach(function(cargs) {
|
|
30
|
+
var rand = cipher.apply(null, cargs);
|
|
31
|
+
var data = Buffer.concat([rand.update(module.exports.bufBest), rand.final()]).slice(0, sz);
|
|
32
|
+
module.exports.bufAvg.push(new Buffer(data));
|
|
33
|
+
|
|
34
|
+
// all yEnc special characters exist in range 0-61 (post shift) or 214-19 (pre-shift)
|
|
35
|
+
// to generate biased data, we'll pack the range down (64-191 will get packed to 192-63)
|
|
36
|
+
for(var i=0; i<data.length; i++) {
|
|
37
|
+
if(data[i] >= 64 && data[i] < 192)
|
|
38
|
+
data[i] = (data[i] + 128) & 0xff;
|
|
39
|
+
}
|
|
40
|
+
module.exports.bufAvg2x.push(data);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
module.exports = {
|
|
44
|
+
size: sz,
|
|
45
|
+
rounds: rounds,
|
|
46
|
+
sleep: 0,
|
|
47
|
+
avgOnly: false,
|
|
48
|
+
decMethods: {'clean':true, 'raw':true, 'incr':true, 'rawincr':true},
|
|
49
|
+
|
|
50
|
+
bufWorst: null,
|
|
51
|
+
bufBest: null,
|
|
52
|
+
bufAvg: null,
|
|
53
|
+
bufAvg2x: null,
|
|
54
|
+
bufTarget: null,
|
|
55
|
+
|
|
56
|
+
bench: function(fn) {
|
|
57
|
+
var times = Array(trials);
|
|
58
|
+
for(var trial=0; trial<trials; trial++) {
|
|
59
|
+
var p=process.hrtime();
|
|
60
|
+
for(var i=0;i<rounds;i++) fn();
|
|
61
|
+
var t=process.hrtime(p);
|
|
62
|
+
|
|
63
|
+
times[trial] = t[0] + t[1]/1000000000;
|
|
64
|
+
}
|
|
65
|
+
// pick fastest time to try to avoid issues with clockspeed throttling
|
|
66
|
+
return Math.min.apply(null, times);
|
|
67
|
+
},
|
|
68
|
+
_benchAsync: function(fn, cb, trials, results) {
|
|
69
|
+
var p=process.hrtime();
|
|
70
|
+
for(var i=0;i<rounds;i++) fn();
|
|
71
|
+
results.push(process.hrtime(p));
|
|
72
|
+
|
|
73
|
+
if(--trials)
|
|
74
|
+
setTimeout(module.exports._benchAsync.bind(null, fn, cb, trials, results), asyncWait);
|
|
75
|
+
else
|
|
76
|
+
cb(Math.min.apply(null, results));
|
|
77
|
+
},
|
|
78
|
+
benchAsync: function(fn, cb) {
|
|
79
|
+
setTimeout(function() {
|
|
80
|
+
module.exports._benchAsync(fn, cb, trials, []);
|
|
81
|
+
}, asyncWait);
|
|
82
|
+
},
|
|
83
|
+
run: function(name, fn, sz2) {
|
|
84
|
+
var time = module.exports.bench(fn);
|
|
85
|
+
console.log(
|
|
86
|
+
(name+' ').substr(0, 25) + ':'
|
|
87
|
+
+ fmtSpeed(sz*rounds, time)
|
|
88
|
+
+ (sz2 ? (' ' + fmtSpeed(sz2*rounds, time)) : '')
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
parseArgs: function(helpText) {
|
|
93
|
+
process.argv.forEach(function(arg) {
|
|
94
|
+
arg = arg.toLowerCase();
|
|
95
|
+
if(arg == '-h' || arg == '--help' || arg == '-?') {
|
|
96
|
+
console.log(helpText + ' [{-z|--size}=bytes('+sz+')] [{-r|--rounds}=num('+rounds+')] [{-t|--trials}=num('+trials+')]');
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
if(arg == '-a' || arg == '--average-only') {
|
|
100
|
+
module.exports.avgOnly = true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var m = arg.match(/^(-s=?|--sleep=)(\d+)$/);
|
|
104
|
+
if(m)
|
|
105
|
+
module.exports.sleep = m[2] |0;
|
|
106
|
+
|
|
107
|
+
m = arg.match(/^(-m=?|--methods=)([a-z,]+)$/);
|
|
108
|
+
if(m) {
|
|
109
|
+
var methods = module.exports.decMethods;
|
|
110
|
+
for(var k in methods)
|
|
111
|
+
methods[k] = false;
|
|
112
|
+
var setAMethod = false;
|
|
113
|
+
m[2].split(',').forEach(function(meth) {
|
|
114
|
+
if(meth in methods) {
|
|
115
|
+
setAMethod = true;
|
|
116
|
+
methods[meth] = true;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
if(!setAMethod) {
|
|
120
|
+
console.log('No valid method specified');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
m = arg.match(/^(-t=?|--trials=)(\d+)$/);
|
|
126
|
+
if(m)
|
|
127
|
+
trials = m[2] |0;
|
|
128
|
+
|
|
129
|
+
m = arg.match(/^(-r=?|--rounds=)(\d+)$/);
|
|
130
|
+
if(m) {
|
|
131
|
+
rounds = m[2] |0;
|
|
132
|
+
module.exports.rounds = rounds;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
m = arg.match(/^(-z=?|--size=)(\d+)$/);
|
|
136
|
+
if(m) {
|
|
137
|
+
sz = m[2] |0;
|
|
138
|
+
module.exports.size = sz;
|
|
139
|
+
initBuffers();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
initBuffers();
|
package/test/speedcrc.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
var y = require('../build/Release/yencode');
|
|
2
|
+
var _ = require('./_speedbase');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
_.parseArgs('Syntax: node test/speedcrc [{-s|--sleep}=msecs(0)]');
|
|
6
|
+
|
|
7
|
+
// warmup
|
|
8
|
+
if(!_.sleep) {
|
|
9
|
+
_.bufAvg.forEach(function(buf, i) {
|
|
10
|
+
var p=process.hrtime();
|
|
11
|
+
for(var i=0;i<_.rounds;i+=2) y.crc32(buf);
|
|
12
|
+
var t=process.hrtime(p);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
setTimeout(function() {
|
|
17
|
+
_.bufAvg.forEach(function(buf, i) {
|
|
18
|
+
_.run('Random ('+i+')', y.crc32.bind(null, buf));
|
|
19
|
+
});
|
|
20
|
+
}, _.sleep);
|
package/test/speeddec.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
var y = require('../build/Release/yencode');
|
|
2
|
+
var _ = require('./_speedbase');
|
|
3
|
+
|
|
4
|
+
var bufSize = _.bufTarget.length;
|
|
5
|
+
|
|
6
|
+
var mWorst = new Buffer(bufSize);
|
|
7
|
+
var mAvg = _.bufAvg.map(function() {
|
|
8
|
+
return new Buffer(bufSize);
|
|
9
|
+
});
|
|
10
|
+
var mAvg2x = _.bufAvg2x.map(function() {
|
|
11
|
+
return new Buffer(bufSize);
|
|
12
|
+
});
|
|
13
|
+
var mBest = new Buffer(bufSize);
|
|
14
|
+
var mBest2 = new Buffer(_.size);
|
|
15
|
+
mBest2.fill(32);
|
|
16
|
+
|
|
17
|
+
var lenWorst = y.encodeTo(_.bufWorst, mWorst);
|
|
18
|
+
var lenBest = y.encodeTo(_.bufBest, mBest);
|
|
19
|
+
var lenAvg = Array(_.bufAvg.length);
|
|
20
|
+
var lenAvg2x = Array(_.bufAvg2x.length);
|
|
21
|
+
_.bufAvg.forEach(function(buf, i) {
|
|
22
|
+
lenAvg[i] = y.encodeTo(buf, mAvg[i]);
|
|
23
|
+
});
|
|
24
|
+
_.bufAvg2x.forEach(function(buf, i) {
|
|
25
|
+
lenAvg2x[i] = y.encodeTo(buf, mAvg2x[i]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
_.parseArgs('Syntax: node test/speeddec [-a|--average-only] [{-s|--sleep}=msecs(0)] [{-m|--methods}=clean,raw,rawincr]');
|
|
31
|
+
|
|
32
|
+
console.log(' Test Output rate Read rate ');
|
|
33
|
+
|
|
34
|
+
// warmup
|
|
35
|
+
if(!_.sleep) {
|
|
36
|
+
mAvg.forEach(function(buf) {
|
|
37
|
+
var p=process.hrtime();
|
|
38
|
+
for(var j=0;j<_.rounds;j+=2) y.decodeTo(buf, _.bufTarget);
|
|
39
|
+
for(var j=0;j<_.rounds;j+=2) y.decodeTo(buf, _.bufTarget, true);
|
|
40
|
+
for(var j=0;j<_.rounds;j+=2) y.decodeIncr(buf, 0, _.bufTarget);
|
|
41
|
+
var t=process.hrtime(p);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setTimeout(function() {
|
|
46
|
+
if(!_.avgOnly) {
|
|
47
|
+
if(_.decMethods.clean) {
|
|
48
|
+
_.run('Clean worst (all escaping)', y.decodeTo.bind(null, mWorst, _.bufTarget), lenWorst);
|
|
49
|
+
_.run('Clean best (min escaping)', y.decodeTo.bind(null, mBest, _.bufTarget), lenBest);
|
|
50
|
+
_.run('Clean pass (no escaping)', y.decodeTo.bind(null, mBest2, _.bufTarget));
|
|
51
|
+
}
|
|
52
|
+
if(_.decMethods.raw) {
|
|
53
|
+
_.run('Raw worst', y.decodeTo.bind(null, mWorst, _.bufTarget, true), lenWorst);
|
|
54
|
+
_.run('Raw best', y.decodeTo.bind(null, mBest, _.bufTarget, true), lenBest);
|
|
55
|
+
_.run('Raw pass', y.decodeTo.bind(null, mBest2, _.bufTarget, true));
|
|
56
|
+
}
|
|
57
|
+
if(_.decMethods.rawincr) {
|
|
58
|
+
_.run('Raw-incr worst', y.decodeIncr.bind(null, mWorst, 0, _.bufTarget), lenWorst);
|
|
59
|
+
_.run('Raw-incr best', y.decodeIncr.bind(null, mBest, 0, _.bufTarget), lenBest);
|
|
60
|
+
_.run('Raw-incr pass', y.decodeIncr.bind(null, mBest2, 0, _.bufTarget));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if(_.decMethods.clean)
|
|
65
|
+
mAvg.forEach(function(buf, i) {
|
|
66
|
+
_.run('Clean random ('+i+')', y.decodeTo.bind(null, buf, _.bufTarget), lenAvg[i]);
|
|
67
|
+
});
|
|
68
|
+
if(_.decMethods.raw)
|
|
69
|
+
mAvg.forEach(function(buf, i) {
|
|
70
|
+
_.run('Raw random ('+i+')', y.decodeTo.bind(null, buf, _.bufTarget, true), lenAvg[i]);
|
|
71
|
+
});
|
|
72
|
+
if(_.decMethods.rawincr) {
|
|
73
|
+
mAvg.forEach(function(buf, i) {
|
|
74
|
+
_.run('Raw-incr random ('+i+')', y.decodeIncr.bind(null, buf, 0, _.bufTarget), lenAvg[i]);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if(!_.avgOnly) {
|
|
79
|
+
if(_.decMethods.clean)
|
|
80
|
+
mAvg2x.forEach(function(buf, i) {
|
|
81
|
+
_.run('Clean random 2xEsc ('+i+')', y.decodeTo.bind(null, buf, _.bufTarget), lenAvg2x[i]);
|
|
82
|
+
});
|
|
83
|
+
if(_.decMethods.raw)
|
|
84
|
+
mAvg2x.forEach(function(buf, i) {
|
|
85
|
+
_.run('Raw random 2xEsc ('+i+')', y.decodeTo.bind(null, buf, _.bufTarget, true), lenAvg2x[i]);
|
|
86
|
+
});
|
|
87
|
+
if(_.decMethods.rawincr)
|
|
88
|
+
mAvg2x.forEach(function(buf, i) {
|
|
89
|
+
_.run('Raw-incr random 2xEsc ('+i+')', y.decodeIncr.bind(null, buf, 0, _.bufTarget), lenAvg2x[i]);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}, _.sleep);
|
package/test/speedenc.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
var y = require('../build/Release/yencode');
|
|
2
|
+
var _ = require('./_speedbase');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
_.parseArgs('Syntax: node test/speedenc [-a|--average-only] [{-s|--sleep}=msecs(0)]');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
console.log(' Test Read rate Output rate ');
|
|
9
|
+
|
|
10
|
+
var lenWorst = y.encodeTo(_.bufWorst, _.bufTarget);
|
|
11
|
+
var lenBest = y.encodeTo(_.bufBest, _.bufTarget);
|
|
12
|
+
var lenAvg = Array(_.bufAvg.length);
|
|
13
|
+
var lenAvg2x = Array(_.bufAvg2x.length);
|
|
14
|
+
|
|
15
|
+
// warmup
|
|
16
|
+
if(!_.sleep) {
|
|
17
|
+
_.bufAvg.forEach(function(buf, i) {
|
|
18
|
+
var p=process.hrtime();
|
|
19
|
+
for(var j=0;j<_.rounds;j+=1) lenAvg[i] = y.encodeTo(buf, _.bufTarget);
|
|
20
|
+
var t=process.hrtime(p);
|
|
21
|
+
});
|
|
22
|
+
_.bufAvg2x.forEach(function(buf, i) {
|
|
23
|
+
var p=process.hrtime();
|
|
24
|
+
for(var j=0;j<_.rounds;j+=1) lenAvg2x[i] = y.encodeTo(buf, _.bufTarget);
|
|
25
|
+
var t=process.hrtime(p);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setTimeout(function() {
|
|
30
|
+
if(!_.avgOnly) {
|
|
31
|
+
_.run('Worst (all escaping)', y.encodeTo.bind(null, _.bufWorst, _.bufTarget), lenWorst);
|
|
32
|
+
_.run('Best (no escaping)', y.encodeTo.bind(null, _.bufBest, _.bufTarget), lenBest);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_.bufAvg.forEach(function(buf, i) {
|
|
36
|
+
_.run('Random ('+i+')', y.encodeTo.bind(null, buf, _.bufTarget), lenAvg[i]);
|
|
37
|
+
});
|
|
38
|
+
if(!_.avgOnly) {
|
|
39
|
+
_.bufAvg2x.forEach(function(buf, i) {
|
|
40
|
+
_.run('Random 2xEsc ('+i+')', y.encodeTo.bind(null, buf, _.bufTarget), lenAvg2x[i]);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}, _.sleep);
|
|
@@ -1,39 +1,53 @@
|
|
|
1
|
-
// a basic script to test that raw yEnc works as expected
|
|
2
|
-
|
|
3
|
-
var assert = require('assert');
|
|
4
|
-
var y =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return
|
|
9
|
-
};
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
doTest('
|
|
25
|
-
doTest('
|
|
26
|
-
|
|
27
|
-
doTest('Join
|
|
28
|
-
doTest('
|
|
29
|
-
doTest('Join
|
|
30
|
-
doTest('Combine
|
|
31
|
-
|
|
32
|
-
doTest('
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
// a basic script to test that raw yEnc works as expected
|
|
2
|
+
|
|
3
|
+
var assert = require('assert');
|
|
4
|
+
var y = (function() {
|
|
5
|
+
try {
|
|
6
|
+
return require('../build/Debug/yencode.node');
|
|
7
|
+
} catch(x) {}
|
|
8
|
+
return require('../build/Release/yencode.node');
|
|
9
|
+
})();
|
|
10
|
+
var crc32 = require('buffer-crc32'); // reference implementation
|
|
11
|
+
|
|
12
|
+
var ycrc32 = function(s) {
|
|
13
|
+
return y.crc32(Buffer(s));
|
|
14
|
+
};
|
|
15
|
+
var doTest = function(msg, f, test, expected) {
|
|
16
|
+
if(!Array.isArray(test)) test = [test];
|
|
17
|
+
test[0] = Buffer(test[0]);
|
|
18
|
+
if(!expected && test.length == 1 && f == 'crc32') expected = crc32(test[0]).toString('hex');
|
|
19
|
+
else if(Buffer.isBuffer(expected)) expected = expected.toString('hex');
|
|
20
|
+
assert.equal(y[f].apply(null, test).toString('hex'), expected, msg);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
doTest('Empty test', 'crc32', '');
|
|
25
|
+
doTest('Single char', 'crc32', 'z');
|
|
26
|
+
doTest('Simple string', 'crc32', 'aabbcc');
|
|
27
|
+
doTest('Join', 'crc32', ['cc', ycrc32('aabb')], crc32('aabbcc'));
|
|
28
|
+
doTest('Combine', 'crc32_combine', [ycrc32('aabb'), crc32('cc'), 2], crc32('aabbcc'));
|
|
29
|
+
doTest('Join 2', 'crc32', ['789012', ycrc32('123456')], crc32('123456789012'));
|
|
30
|
+
doTest('Combine 2', 'crc32_combine', [ycrc32('123456'), crc32('789012'), 6], crc32('123456789012'));
|
|
31
|
+
|
|
32
|
+
doTest('Join Empty', 'crc32', ['', ycrc32('z')], crc32('z'));
|
|
33
|
+
doTest('Join Empty 2', 'crc32', ['z', ycrc32('')], crc32('z'));
|
|
34
|
+
doTest('Join Empty 3', 'crc32', ['', ycrc32('')], crc32(''));
|
|
35
|
+
doTest('Combine Empty', 'crc32_combine', [ycrc32(''), ycrc32('z'), 1], crc32('z'));
|
|
36
|
+
doTest('Combine Empty 2', 'crc32_combine', [ycrc32('z'), ycrc32(''), 0], crc32('z'));
|
|
37
|
+
doTest('Combine Empty 3', 'crc32_combine', [ycrc32(''), ycrc32(''), 0], crc32(''));
|
|
38
|
+
|
|
39
|
+
assert.equal(y.crc32_zeroes(0).toString('hex'), '00000000', 'Zeroes (0)');
|
|
40
|
+
assert.equal(y.crc32_zeroes(1).toString('hex'), 'd202ef8d', 'Zeroes (1)');
|
|
41
|
+
assert.equal(y.crc32_zeroes(4).toString('hex'), '2144df1c', 'Zeroes (4)');
|
|
42
|
+
|
|
43
|
+
assert.equal(y.crc32_zeroes(0, ycrc32('')).toString('hex'), '00000000', 'Zeroes-Join (0)');
|
|
44
|
+
assert.equal(y.crc32_zeroes(1, ycrc32('')).toString('hex'), 'd202ef8d', 'Zeroes-Join (1)');
|
|
45
|
+
assert.equal(y.crc32_zeroes(0, ycrc32('z')).toString('hex'), crc32('z').toString('hex'), 'Zeroes Empty Join');
|
|
46
|
+
assert.equal(y.crc32_zeroes(4, ycrc32('z')).toString('hex'), crc32('z\u0000\u0000\u0000\u0000').toString('hex'), 'Zeroes (4) Join');
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
doTest('Random', 'crc32', 'fj[-oqijnw34-59n26 4345j8yn89032q78t9ab9gabh023quhoiBO Z GEB780a sdasdq2345673-98hq2-9348h-na9we8zdfgh-n9 8qwhn-098');
|
|
50
|
+
doTest('Random Continue', 'crc32', ['KZSHZ5EDOVAmDdakZZOrGSUGGKSpCJoWH7M0MHy6ohnSzvHY4DjpxXmyfWYJQoJ7tKdNhGcuRVUzrgXM', ycrc32('BdenbmoBgiB10ZkeUBjrsZV3dg2Da2fhHqU9TMdi69AHhLRck3Nk60YuFBXh6lvtefBpjdTxbeEmsaEm')], crc32('BdenbmoBgiB10ZkeUBjrsZV3dg2Da2fhHqU9TMdi69AHhLRck3Nk60YuFBXh6lvtefBpjdTxbeEmsaEmKZSHZ5EDOVAmDdakZZOrGSUGGKSpCJoWH7M0MHy6ohnSzvHY4DjpxXmyfWYJQoJ7tKdNhGcuRVUzrgXM'));
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
console.log('All tests passed');
|
package/test/testdec.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// a basic script to test that raw yEnc works as expected
|
|
2
|
+
|
|
3
|
+
var assert = require('assert');
|
|
4
|
+
var y = (function() {
|
|
5
|
+
try {
|
|
6
|
+
return require('../build/Debug/yencode.node');
|
|
7
|
+
} catch(x) {}
|
|
8
|
+
return require('../build/Release/yencode.node');
|
|
9
|
+
})();
|
|
10
|
+
|
|
11
|
+
var ord = function(c) {
|
|
12
|
+
return c.charCodeAt(0);
|
|
13
|
+
}, chr = String.fromCharCode;
|
|
14
|
+
// slow reference yEnc implementation
|
|
15
|
+
var refYDec = function(src, findEnd) {
|
|
16
|
+
var ret = [];
|
|
17
|
+
if(findEnd && chr(src[0]) == '=' && chr(src[1]) == 'y') return new Buffer(0);
|
|
18
|
+
for (var i = 0; i < src.length; i++) {
|
|
19
|
+
switch(chr(src[i])) {
|
|
20
|
+
case '\r':
|
|
21
|
+
if(findEnd && chr(src[i+1]) == '\n' && chr(src[i+2]) == '=' && chr(src[i+3]) == 'y')
|
|
22
|
+
return new Buffer(ret);
|
|
23
|
+
case '\n': continue;
|
|
24
|
+
case '=':
|
|
25
|
+
i++;
|
|
26
|
+
if(i < src.length)
|
|
27
|
+
ret.push((src[i] - 42 - 64) & 0xFF);
|
|
28
|
+
if(chr(src[i]) == '\r') i--;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
ret.push((src[i] - 42) & 0xFF);
|
|
32
|
+
}
|
|
33
|
+
return new Buffer(ret);
|
|
34
|
+
};
|
|
35
|
+
var refYDecRaw = function(src, findEnd) {
|
|
36
|
+
// undo NNTP layer
|
|
37
|
+
var data = [];
|
|
38
|
+
var i = 0;
|
|
39
|
+
if(src[0] == ord('.')) {
|
|
40
|
+
i++;
|
|
41
|
+
if(findEnd && src[1] == ord('\r') && src[2] == ord('\n'))
|
|
42
|
+
return new Buffer(0);
|
|
43
|
+
}
|
|
44
|
+
// TODO: do leading/trailing spaces/tabs need to be trimmed?
|
|
45
|
+
for(; i<src.length; i++) {
|
|
46
|
+
if(src[i] == ord('\r') && src[i+1] == ord('\n') && src[i+2] == ord('.')) {
|
|
47
|
+
data.push(src[i], src[i+1]);
|
|
48
|
+
if(findEnd && src[i+3] == ord('\r') && src[i+4] == ord('\n')) {
|
|
49
|
+
// it's a little vague how this is exactly handled, but we'll push a \r\n to the yenc decoder (above line)
|
|
50
|
+
// doing so means that =\r\n.\r\n will generate a single escaped character
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
i += 2;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
data.push(src[i]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return refYDec(data, findEnd);
|
|
60
|
+
};
|
|
61
|
+
var testFuncs = [
|
|
62
|
+
{l: 'nntp', r: refYDecRaw, a: function(s) {
|
|
63
|
+
return y.decode(s, true);
|
|
64
|
+
}},
|
|
65
|
+
{l: 'plain', r: refYDec, a: y.decode},
|
|
66
|
+
{l: 'nntp-end', r: function(s) {
|
|
67
|
+
return refYDecRaw(s, true);
|
|
68
|
+
}, a: function(s) {
|
|
69
|
+
if(!s.length) return Buffer(0);
|
|
70
|
+
return y.decodeIncr(s).output;
|
|
71
|
+
}}
|
|
72
|
+
];
|
|
73
|
+
var doTest = function(msg, data, expected) {
|
|
74
|
+
data = new Buffer(data);
|
|
75
|
+
|
|
76
|
+
var prepad = 48, postpad = 48;
|
|
77
|
+
if(data.length > 1024) {
|
|
78
|
+
prepad = 1;
|
|
79
|
+
postpad = 1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for(var i=0; i<prepad; i++) {
|
|
83
|
+
var pre = new Buffer(i);
|
|
84
|
+
pre.fill(1);
|
|
85
|
+
for(var j=0; j<postpad; j++) {
|
|
86
|
+
testFuncs.forEach(function(f) {
|
|
87
|
+
var post = new Buffer(j);
|
|
88
|
+
post.fill(1);
|
|
89
|
+
|
|
90
|
+
var testData = Buffer.concat([pre, data, post]);
|
|
91
|
+
var x;
|
|
92
|
+
if(expected === undefined) x = f.r(testData).toString('hex');
|
|
93
|
+
else x = new Buffer(expected).toString('hex').replace(/ /g, '');
|
|
94
|
+
var actual = f.a(testData).toString('hex');
|
|
95
|
+
if(actual != x) {
|
|
96
|
+
console.log('Actual:', actual);
|
|
97
|
+
console.log('Expect:', x);
|
|
98
|
+
console.log('Source:', data.toString('hex'));
|
|
99
|
+
assert.equal(actual, x, msg + ' [' + i + '/' + j + ' ' + f.l + ']');
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
if(expected !== undefined) return; // if given expected string, only do one test
|
|
103
|
+
|
|
104
|
+
// TODO: test various states
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
doTest('Empty test', [], '');
|
|
111
|
+
doTest('Simple test', [0,1,2,10,3,61,64]);
|
|
112
|
+
doTest('Just newline', [10], '');
|
|
113
|
+
doTest('Just equals', [61], '');
|
|
114
|
+
doTest('Equal+newline', [61, 13], [163]);
|
|
115
|
+
doTest('Equal+equal', [61, 61], [211]);
|
|
116
|
+
doTest('Equal+equal+newline', [61, 61, 13], [211]);
|
|
117
|
+
doTest('Newline, equal', [10, 61], '');
|
|
118
|
+
doTest('Stripped dot', [13, 10, 46]);
|
|
119
|
+
doTest('Just dot', [46]);
|
|
120
|
+
doTest('Consecutive stripped dot', [13, 10, 46, 13, 10, 46]);
|
|
121
|
+
doTest('Bad escape stripped dot', [61, 13, 10, 46]);
|
|
122
|
+
|
|
123
|
+
doTest('NNTP end sequence', '\r\n.\r\n');
|
|
124
|
+
doTest('NNTP end sequence (2)', '.\r\n');
|
|
125
|
+
doTest('Yenc end sequence', '\r\n=y');
|
|
126
|
+
doTest('Yenc end sequence (2)', '=y');
|
|
127
|
+
doTest('Mixed end sequence', '\r\n=y\r\n.\r\n');
|
|
128
|
+
doTest('Mixed end sequence (2)', '\r\n.\r\n=y');
|
|
129
|
+
doTest('Not end sequence', '\r\n=abc');
|
|
130
|
+
doTest('Dot stuffed end sequence', '\r\n.=y');
|
|
131
|
+
doTest('Dot stuffed bad escape sequence', '\r\n.=.');
|
|
132
|
+
doTest('Broken end sequence', '\r\n.\ra\n');
|
|
133
|
+
doTest('NNTP end sequence, badly dot stuffed', '\r\n..\r\n');
|
|
134
|
+
doTest('NNTP end sequence, badly dot stuffed (2)', '\r\n.a=y');
|
|
135
|
+
doTest('Bad escape, NNTP end sequence', '=\r\n.\r\n');
|
|
136
|
+
doTest('Bad escape, Yenc end sequence', '=\r\n=y');
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
// longer tests
|
|
140
|
+
var b = new Buffer(256);
|
|
141
|
+
b.fill(0);
|
|
142
|
+
doTest('Long no escaping', b);
|
|
143
|
+
b.fill('='.charCodeAt(0));
|
|
144
|
+
doTest('Long all equals', b);
|
|
145
|
+
for(var i=1; i<b.length; i+=2)
|
|
146
|
+
b[i] = 64;
|
|
147
|
+
doTest('Long all escaped nulls', b);
|
|
148
|
+
b.fill('='.charCodeAt(0));
|
|
149
|
+
for(var i=0; i<b.length; i+=2)
|
|
150
|
+
b[i] = 64;
|
|
151
|
+
doTest('Long all invalid escaped nulls', b);
|
|
152
|
+
b.fill(10);
|
|
153
|
+
doTest('Long all newlines', b);
|
|
154
|
+
b.fill(223);
|
|
155
|
+
doTest('Long all tabs', b);
|
|
156
|
+
|
|
157
|
+
// test for past bug in ARMv8 NEON decoder where nextMask wasn't properly compensated for
|
|
158
|
+
doTest('Extra null issue', new Buffer('2e900a4fb6054c9126171cdc196dc41237bb1b76da9191aa5e85c1d2a2a5c638fe39054a210e8c799473cd510541fd118f3904b242a9938558c879238aae1d3bdab32e287cedb820b494f54ffae6dd0b13f73a4a9499df486a7845c612182bcef72a6e50a8e98351c35765d26c605115dc8c5c56a5e3f20ae6da8dcd78536e6d1601eb1fc3ddc774', 'hex'));
|
|
159
|
+
// end detection bug
|
|
160
|
+
doTest('End detect', new Buffer('612e6161610d610d612e793d3d0d0d2e612e2e0a0d0d61792e3d3d61612e0d0a2e0d2e0a0d79612e0a3d2e2e793d2e610a0d0a0a2e793d790d612e61612e0a3d792e2e3d2e7961793d792e0a61790a0d0a2e0d0a3d0a0d0d0d0a610a0a6161792e3d2e0a2e0d0d0d613d610a0a0a793d613d3d0a3d790d3d0a0a2e2e7979796179613d0d2e792e793d3d61792e612e2e2e793d616161790d0d2e0d0d793d0d790a0a3d0d617979790d2e0d792e612e610a0a0a0a0a79790d0a610d612e0d0a0d3d0a61792e2e0a790d0d792e790d0a2e79612e3d0a79790a0d0d3d0a0a0d3d0a7961610a2e613d792e0a612e613d610a2e0a0a79613d2e2e0d3d3d2e793d792e792e0d0d610d2e2e0d2e79610d2e790d790d3d2e3d790a0a0d0a0a0a612e2e79612e0d2e3d793d2e0a2e3d790a2e3d792e2e610d3d2e0d3d3d0a3d2e0d613d2e0d61610a3d0a2e0a0a3d3d612e3d790d6161613d3d612e3d0d0a2e0d0d0d616179790a2e3d610d612e0d2e3d0d0a3d610d0d61610a7961613d2e790d613d610a3d612e0a2e0d79790d0a610a2e2e0a2e612e2e0d792e61610a2e0d610d3d0a793d613d0d3d0a3d0d0a613d2e0a3d610a3d0d793d0d7979792e3d613d0a2e61610d793d2e0a0a2e612e0d2e2e792e0d2e613d0d790a0d2e610d2e0a2e61793d0d0d0a0a0d0d2e2e0d2e793d3d79612e0a610a610a0d610d0d2e2e790', 'hex'));
|
|
161
|
+
|
|
162
|
+
// random tests
|
|
163
|
+
for(var i=0; i<32; i++) {
|
|
164
|
+
var rand = require('crypto').pseudoRandomBytes(128*1024);
|
|
165
|
+
doTest('Random', rand);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// targeted random tests
|
|
169
|
+
var charset = '=\r\n.ay';
|
|
170
|
+
var randStr = function(n) {
|
|
171
|
+
var ret = new Buffer(n);
|
|
172
|
+
for(var i=0; i<n; i++)
|
|
173
|
+
ret[i] = ord(charset[(Math.random() * charset.length) | 0]);
|
|
174
|
+
return ret;
|
|
175
|
+
};
|
|
176
|
+
for(var i=0; i<128; i++) {
|
|
177
|
+
var rand = randStr(2048);
|
|
178
|
+
doTest('Random2', rand);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
console.log('All tests passed');
|