Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80529 views
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
var assert = require('assert');
23
var zlib = require('../');
24
var path = require('path');
25
26
var zlibPairs =
27
[[zlib.Deflate, zlib.Inflate],
28
[zlib.Gzip, zlib.Gunzip],
29
[zlib.Deflate, zlib.Unzip],
30
[zlib.Gzip, zlib.Unzip],
31
[zlib.DeflateRaw, zlib.InflateRaw]];
32
33
// how fast to trickle through the slowstream
34
var trickle = [128, 1024, 1024 * 1024];
35
36
// tunable options for zlib classes.
37
38
// several different chunk sizes
39
var chunkSize = [128, 1024, 1024 * 16, 1024 * 1024];
40
41
// this is every possible value.
42
var level = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
43
var windowBits = [8, 9, 10, 11, 12, 13, 14, 15];
44
var memLevel = [1, 2, 3, 4, 5, 6, 7, 8, 9];
45
var strategy = [0, 1, 2, 3, 4];
46
47
// it's nice in theory to test every combination, but it
48
// takes WAY too long. Maybe a pummel test could do this?
49
if (!process.env.PUMMEL) {
50
trickle = [1024];
51
chunkSize = [1024 * 16];
52
level = [6];
53
memLevel = [8];
54
windowBits = [15];
55
strategy = [0];
56
}
57
58
var fs = require('fs');
59
60
if (process.env.FAST) {
61
zlibPairs = [[zlib.Gzip, zlib.Unzip]];
62
}
63
64
var tests = {
65
'person.jpg': fs.readFileSync(__dirname + '/fixtures/person.jpg'),
66
'elipses.txt': fs.readFileSync(__dirname + '/fixtures/elipses.txt'),
67
'empty.txt': fs.readFileSync(__dirname + '/fixtures/empty.txt')
68
};
69
70
var util = require('util');
71
var stream = require('stream');
72
73
74
// stream that saves everything
75
function BufferStream() {
76
this.chunks = [];
77
this.length = 0;
78
this.writable = true;
79
this.readable = true;
80
}
81
82
util.inherits(BufferStream, stream.Stream);
83
84
BufferStream.prototype.write = function(c) {
85
this.chunks.push(c);
86
this.length += c.length;
87
return true;
88
};
89
90
BufferStream.prototype.end = function(c) {
91
if (c) this.write(c);
92
// flatten
93
var buf = new Buffer(this.length);
94
var i = 0;
95
this.chunks.forEach(function(c) {
96
c.copy(buf, i);
97
i += c.length;
98
});
99
this.emit('data', buf);
100
this.emit('end');
101
return true;
102
};
103
104
105
function SlowStream(trickle) {
106
this.trickle = trickle;
107
this.offset = 0;
108
this.readable = this.writable = true;
109
}
110
111
util.inherits(SlowStream, stream.Stream);
112
113
SlowStream.prototype.write = function() {
114
throw new Error('not implemented, just call ss.end(chunk)');
115
};
116
117
SlowStream.prototype.pause = function() {
118
this.paused = true;
119
this.emit('pause');
120
};
121
122
SlowStream.prototype.resume = function() {
123
var self = this;
124
if (self.ended) return;
125
self.emit('resume');
126
if (!self.chunk) return;
127
self.paused = false;
128
emit();
129
function emit() {
130
if (self.paused) return;
131
if (self.offset >= self.length) {
132
self.ended = true;
133
return self.emit('end');
134
}
135
var end = Math.min(self.offset + self.trickle, self.length);
136
var c = self.chunk.slice(self.offset, end);
137
self.offset += c.length;
138
self.emit('data', c);
139
process.nextTick(emit);
140
}
141
};
142
143
SlowStream.prototype.end = function(chunk) {
144
// walk over the chunk in blocks.
145
var self = this;
146
self.chunk = chunk;
147
self.length = chunk.length;
148
self.resume();
149
return self.ended;
150
};
151
152
153
154
// for each of the files, make sure that compressing and
155
// decompressing results in the same data, for every combination
156
// of the options set above.
157
var tape = require('tape');
158
159
Object.keys(tests).forEach(function(file) {
160
var test = tests[file];
161
chunkSize.forEach(function(chunkSize) {
162
trickle.forEach(function(trickle) {
163
windowBits.forEach(function(windowBits) {
164
level.forEach(function(level) {
165
memLevel.forEach(function(memLevel) {
166
strategy.forEach(function(strategy) {
167
zlibPairs.forEach(function(pair) {
168
var Def = pair[0];
169
var Inf = pair[1];
170
var opts = {
171
level: level,
172
windowBits: windowBits,
173
memLevel: memLevel,
174
strategy: strategy
175
};
176
177
var msg = file + ' ' +
178
chunkSize + ' ' +
179
JSON.stringify(opts) + ' ' +
180
Def.name + ' -> ' + Inf.name;
181
182
tape('zlib ' + msg, function(t) {
183
t.plan(1);
184
185
var def = new Def(opts);
186
var inf = new Inf(opts);
187
var ss = new SlowStream(trickle);
188
var buf = new BufferStream();
189
190
// verify that the same exact buffer comes out the other end.
191
buf.on('data', function(c) {
192
t.deepEqual(c, test);
193
});
194
195
// the magic happens here.
196
ss.pipe(def).pipe(inf).pipe(buf);
197
ss.end(test);
198
});
199
});
200
});
201
});
202
});
203
});
204
});
205
});
206
});
207
208