test-zlib.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. var assert = require('assert');
  22. var zlib = require('../');
  23. var path = require('path');
  24. var zlibPairs =
  25. [[zlib.Deflate, zlib.Inflate],
  26. [zlib.Gzip, zlib.Gunzip],
  27. [zlib.Deflate, zlib.Unzip],
  28. [zlib.Gzip, zlib.Unzip],
  29. [zlib.DeflateRaw, zlib.InflateRaw]];
  30. // how fast to trickle through the slowstream
  31. var trickle = [128, 1024, 1024 * 1024];
  32. // tunable options for zlib classes.
  33. // several different chunk sizes
  34. var chunkSize = [128, 1024, 1024 * 16, 1024 * 1024];
  35. // this is every possible value.
  36. var level = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  37. var windowBits = [8, 9, 10, 11, 12, 13, 14, 15];
  38. var memLevel = [1, 2, 3, 4, 5, 6, 7, 8, 9];
  39. var strategy = [0, 1, 2, 3, 4];
  40. // it's nice in theory to test every combination, but it
  41. // takes WAY too long. Maybe a pummel test could do this?
  42. if (!process.env.PUMMEL) {
  43. trickle = [1024];
  44. chunkSize = [1024 * 16];
  45. level = [6];
  46. memLevel = [8];
  47. windowBits = [15];
  48. strategy = [0];
  49. }
  50. var fs = require('fs');
  51. if (process.env.FAST) {
  52. zlibPairs = [[zlib.Gzip, zlib.Unzip]];
  53. }
  54. var tests = {
  55. 'person.jpg': fs.readFileSync(__dirname + '/fixtures/person.jpg'),
  56. 'elipses.txt': fs.readFileSync(__dirname + '/fixtures/elipses.txt'),
  57. 'empty.txt': fs.readFileSync(__dirname + '/fixtures/empty.txt')
  58. };
  59. var util = require('util');
  60. var stream = require('stream');
  61. // stream that saves everything
  62. function BufferStream() {
  63. this.chunks = [];
  64. this.length = 0;
  65. this.writable = true;
  66. this.readable = true;
  67. }
  68. util.inherits(BufferStream, stream.Stream);
  69. BufferStream.prototype.write = function(c) {
  70. this.chunks.push(c);
  71. this.length += c.length;
  72. return true;
  73. };
  74. BufferStream.prototype.end = function(c) {
  75. if (c) this.write(c);
  76. // flatten
  77. var buf = new Buffer(this.length);
  78. var i = 0;
  79. this.chunks.forEach(function(c) {
  80. c.copy(buf, i);
  81. i += c.length;
  82. });
  83. this.emit('data', buf);
  84. this.emit('end');
  85. return true;
  86. };
  87. function SlowStream(trickle) {
  88. this.trickle = trickle;
  89. this.offset = 0;
  90. this.readable = this.writable = true;
  91. }
  92. util.inherits(SlowStream, stream.Stream);
  93. SlowStream.prototype.write = function() {
  94. throw new Error('not implemented, just call ss.end(chunk)');
  95. };
  96. SlowStream.prototype.pause = function() {
  97. this.paused = true;
  98. this.emit('pause');
  99. };
  100. SlowStream.prototype.resume = function() {
  101. var self = this;
  102. if (self.ended) return;
  103. self.emit('resume');
  104. if (!self.chunk) return;
  105. self.paused = false;
  106. emit();
  107. function emit() {
  108. if (self.paused) return;
  109. if (self.offset >= self.length) {
  110. self.ended = true;
  111. return self.emit('end');
  112. }
  113. var end = Math.min(self.offset + self.trickle, self.length);
  114. var c = self.chunk.slice(self.offset, end);
  115. self.offset += c.length;
  116. self.emit('data', c);
  117. process.nextTick(emit);
  118. }
  119. };
  120. SlowStream.prototype.end = function(chunk) {
  121. // walk over the chunk in blocks.
  122. var self = this;
  123. self.chunk = chunk;
  124. self.length = chunk.length;
  125. self.resume();
  126. return self.ended;
  127. };
  128. // for each of the files, make sure that compressing and
  129. // decompressing results in the same data, for every combination
  130. // of the options set above.
  131. var tape = require('tape');
  132. Object.keys(tests).forEach(function(file) {
  133. var test = tests[file];
  134. chunkSize.forEach(function(chunkSize) {
  135. trickle.forEach(function(trickle) {
  136. windowBits.forEach(function(windowBits) {
  137. level.forEach(function(level) {
  138. memLevel.forEach(function(memLevel) {
  139. strategy.forEach(function(strategy) {
  140. zlibPairs.forEach(function(pair) {
  141. var Def = pair[0];
  142. var Inf = pair[1];
  143. var opts = {
  144. level: level,
  145. windowBits: windowBits,
  146. memLevel: memLevel,
  147. strategy: strategy
  148. };
  149. var msg = file + ' ' +
  150. chunkSize + ' ' +
  151. JSON.stringify(opts) + ' ' +
  152. Def.name + ' -> ' + Inf.name;
  153. tape('zlib ' + msg, function(t) {
  154. t.plan(1);
  155. var def = new Def(opts);
  156. var inf = new Inf(opts);
  157. var ss = new SlowStream(trickle);
  158. var buf = new BufferStream();
  159. // verify that the same exact buffer comes out the other end.
  160. buf.on('data', function(c) {
  161. t.deepEqual(c, test);
  162. });
  163. // the magic happens here.
  164. ss.pipe(def).pipe(inf).pipe(buf);
  165. ss.end(test);
  166. });
  167. });
  168. });
  169. });
  170. });
  171. });
  172. });
  173. });
  174. });