1'use strict'; 2 3const common = require('../common'); 4const { Readable } = require('stream'); 5const assert = require('assert'); 6 7{ 8 const read = new Readable({ 9 read() {} 10 }); 11 read.resume(); 12 13 read.on('close', common.mustCall()); 14 15 read.destroy(); 16 assert.strictEqual(read.destroyed, true); 17} 18 19{ 20 const read = new Readable({ 21 read() {} 22 }); 23 read.resume(); 24 25 const expected = new Error('kaboom'); 26 27 read.on('end', common.mustNotCall('no end event')); 28 read.on('close', common.mustCall()); 29 read.on('error', common.mustCall((err) => { 30 assert.strictEqual(err, expected); 31 })); 32 33 read.destroy(expected); 34 assert.strictEqual(read.destroyed, true); 35} 36 37{ 38 const read = new Readable({ 39 read() {} 40 }); 41 42 read._destroy = common.mustCall(function(err, cb) { 43 assert.strictEqual(err, expected); 44 cb(err); 45 }); 46 47 const expected = new Error('kaboom'); 48 49 read.on('end', common.mustNotCall('no end event')); 50 read.on('close', common.mustCall()); 51 read.on('error', common.mustCall((err) => { 52 assert.strictEqual(err, expected); 53 })); 54 55 read.destroy(expected); 56 assert.strictEqual(read.destroyed, true); 57} 58 59{ 60 const read = new Readable({ 61 read() {}, 62 destroy: common.mustCall(function(err, cb) { 63 assert.strictEqual(err, expected); 64 cb(); 65 }) 66 }); 67 68 const expected = new Error('kaboom'); 69 70 read.on('end', common.mustNotCall('no end event')); 71 72 // Error is swallowed by the custom _destroy 73 read.on('error', common.mustNotCall('no error event')); 74 read.on('close', common.mustCall()); 75 76 read.destroy(expected); 77 assert.strictEqual(read.destroyed, true); 78} 79 80{ 81 const read = new Readable({ 82 read() {} 83 }); 84 85 read._destroy = common.mustCall(function(err, cb) { 86 assert.strictEqual(err, null); 87 cb(); 88 }); 89 90 read.destroy(); 91 assert.strictEqual(read.destroyed, true); 92} 93 94{ 95 const read = new Readable({ 96 read() {} 97 }); 98 read.resume(); 99 100 read._destroy = common.mustCall(function(err, cb) { 101 assert.strictEqual(err, null); 102 process.nextTick(() => { 103 this.push(null); 104 cb(); 105 }); 106 }); 107 108 const fail = common.mustNotCall('no end event'); 109 110 read.on('end', fail); 111 read.on('close', common.mustCall()); 112 113 read.destroy(); 114 115 read.removeListener('end', fail); 116 read.on('end', common.mustNotCall()); 117 assert.strictEqual(read.destroyed, true); 118} 119 120{ 121 const read = new Readable({ 122 read() {} 123 }); 124 125 const expected = new Error('kaboom'); 126 127 read._destroy = common.mustCall(function(err, cb) { 128 assert.strictEqual(err, null); 129 cb(expected); 130 }); 131 132 let ticked = false; 133 read.on('end', common.mustNotCall('no end event')); 134 read.on('error', common.mustCall((err) => { 135 assert.strictEqual(ticked, true); 136 assert.strictEqual(read._readableState.errorEmitted, true); 137 assert.strictEqual(read._readableState.errored, expected); 138 assert.strictEqual(err, expected); 139 })); 140 141 read.destroy(); 142 assert.strictEqual(read._readableState.errorEmitted, false); 143 assert.strictEqual(read._readableState.errored, expected); 144 assert.strictEqual(read.destroyed, true); 145 ticked = true; 146} 147 148{ 149 const read = new Readable({ 150 read() {} 151 }); 152 read.resume(); 153 154 read.destroyed = true; 155 assert.strictEqual(read.destroyed, true); 156 157 // The internal destroy() mechanism should not be triggered 158 read.on('end', common.mustNotCall()); 159 read.destroy(); 160} 161 162{ 163 function MyReadable() { 164 assert.strictEqual(this.destroyed, false); 165 this.destroyed = false; 166 Readable.call(this); 167 } 168 169 Object.setPrototypeOf(MyReadable.prototype, Readable.prototype); 170 Object.setPrototypeOf(MyReadable, Readable); 171 172 new MyReadable(); 173} 174 175{ 176 // Destroy and destroy callback 177 const read = new Readable({ 178 read() {} 179 }); 180 read.resume(); 181 182 const expected = new Error('kaboom'); 183 184 let ticked = false; 185 read.on('close', common.mustCall(() => { 186 assert.strictEqual(read._readableState.errorEmitted, true); 187 assert.strictEqual(ticked, true); 188 })); 189 read.on('error', common.mustCall((err) => { 190 assert.strictEqual(err, expected); 191 })); 192 193 assert.strictEqual(read._readableState.errored, null); 194 assert.strictEqual(read._readableState.errorEmitted, false); 195 196 read.destroy(expected, common.mustCall(function(err) { 197 assert.strictEqual(read._readableState.errored, expected); 198 assert.strictEqual(err, expected); 199 })); 200 assert.strictEqual(read._readableState.errorEmitted, false); 201 assert.strictEqual(read._readableState.errored, expected); 202 ticked = true; 203} 204 205{ 206 const readable = new Readable({ 207 destroy: common.mustCall(function(err, cb) { 208 process.nextTick(cb, new Error('kaboom 1')); 209 }), 210 read() {} 211 }); 212 213 let ticked = false; 214 readable.on('close', common.mustCall(() => { 215 assert.strictEqual(ticked, true); 216 assert.strictEqual(readable._readableState.errorEmitted, true); 217 })); 218 readable.on('error', common.mustCall((err) => { 219 assert.strictEqual(ticked, true); 220 assert.strictEqual(err.message, 'kaboom 1'); 221 assert.strictEqual(readable._readableState.errorEmitted, true); 222 })); 223 224 readable.destroy(); 225 assert.strictEqual(readable.destroyed, true); 226 assert.strictEqual(readable._readableState.errored, null); 227 assert.strictEqual(readable._readableState.errorEmitted, false); 228 229 // Test case where `readable.destroy()` is called again with an error before 230 // the `_destroy()` callback is called. 231 readable.destroy(new Error('kaboom 2')); 232 assert.strictEqual(readable._readableState.errorEmitted, false); 233 assert.strictEqual(readable._readableState.errored, null); 234 235 ticked = true; 236} 237 238{ 239 const read = new Readable({ 240 read() {} 241 }); 242 243 read.destroy(); 244 read.push('hi'); 245 read.on('data', common.mustNotCall()); 246} 247 248{ 249 const read = new Readable({ 250 read: common.mustNotCall(function() {}) 251 }); 252 read.destroy(); 253 assert.strictEqual(read.destroyed, true); 254 read.read(); 255} 256 257{ 258 const read = new Readable({ 259 autoDestroy: false, 260 read() { 261 this.push(null); 262 this.push('asd'); 263 } 264 }); 265 266 read.on('error', common.mustCall(() => { 267 assert(read._readableState.errored); 268 })); 269 read.resume(); 270} 271