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'use strict';
23const common = require('../common');
24const assert = require('assert');
25
26const stream = require('stream');
27
28const queue = [];
29for (let decode = 0; decode < 2; decode++) {
30  for (let uncork = 0; uncork < 2; uncork++) {
31    for (let multi = 0; multi < 2; multi++) {
32      queue.push([!!decode, !!uncork, !!multi]);
33    }
34  }
35}
36
37run();
38
39function run() {
40  const t = queue.pop();
41  if (t)
42    test(t[0], t[1], t[2], run);
43  else
44    console.log('ok');
45}
46
47function test(decode, uncork, multi, next) {
48  console.log(`# decode=${decode} uncork=${uncork} multi=${multi}`);
49  let counter = 0;
50  let expectCount = 0;
51  function cnt(msg) {
52    expectCount++;
53    const expect = expectCount;
54    return function(er) {
55      assert.ifError(er);
56      counter++;
57      assert.strictEqual(counter, expect);
58    };
59  }
60
61  const w = new stream.Writable({ decodeStrings: decode });
62  w._write = common.mustNotCall('Should not call _write');
63
64  const expectChunks = decode ? [
65    { encoding: 'buffer',
66      chunk: [104, 101, 108, 108, 111, 44, 32] },
67    { encoding: 'buffer',
68      chunk: [119, 111, 114, 108, 100] },
69    { encoding: 'buffer',
70      chunk: [33] },
71    { encoding: 'buffer',
72      chunk: [10, 97, 110, 100, 32, 116, 104, 101, 110, 46, 46, 46] },
73    { encoding: 'buffer',
74      chunk: [250, 206, 190, 167, 222, 173, 190, 239, 222, 202, 251, 173] },
75  ] : [
76    { encoding: 'ascii', chunk: 'hello, ' },
77    { encoding: 'utf8', chunk: 'world' },
78    { encoding: 'buffer', chunk: [33] },
79    { encoding: 'latin1', chunk: '\nand then...' },
80    { encoding: 'hex', chunk: 'facebea7deadbeefdecafbad' },
81  ];
82
83  let actualChunks;
84  w._writev = function(chunks, cb) {
85    actualChunks = chunks.map(function(chunk) {
86      return {
87        encoding: chunk.encoding,
88        chunk: Buffer.isBuffer(chunk.chunk) ?
89          Array.prototype.slice.call(chunk.chunk) : chunk.chunk
90      };
91    });
92    cb();
93  };
94
95  w.cork();
96  w.write('hello, ', 'ascii', cnt('hello'));
97  w.write('world', 'utf8', cnt('world'));
98
99  if (multi)
100    w.cork();
101
102  w.write(Buffer.from('!'), 'buffer', cnt('!'));
103  w.write('\nand then...', 'latin1', cnt('and then'));
104
105  if (multi)
106    w.uncork();
107
108  w.write('facebea7deadbeefdecafbad', 'hex', cnt('hex'));
109
110  if (uncork)
111    w.uncork();
112
113  w.end(cnt('end'));
114
115  w.on('finish', function() {
116    // Make sure finish comes after all the write cb
117    cnt('finish')();
118    assert.deepStrictEqual(actualChunks, expectChunks);
119    next();
120  });
121}
122
123{
124  const w = new stream.Writable({
125    writev: common.mustCall(function(chunks, cb) {
126      cb();
127    })
128  });
129  w.write('asd', common.mustCall());
130}
131