1'use strict';
2
3require('../common');
4const assert = require('assert');
5
6const b = Buffer.allocUnsafe(1024);
7const c = Buffer.allocUnsafe(512);
8
9let cntr = 0;
10
11{
12  // copy 512 bytes, from 0 to 512.
13  b.fill(++cntr);
14  c.fill(++cntr);
15  const copied = b.copy(c, 0, 0, 512);
16  assert.strictEqual(copied, 512);
17  for (let i = 0; i < c.length; i++) {
18    assert.strictEqual(c[i], b[i]);
19  }
20}
21
22{
23  // Current behavior is to coerce values to integers.
24  b.fill(++cntr);
25  c.fill(++cntr);
26  const copied = b.copy(c, '0', '0', '512');
27  assert.strictEqual(copied, 512);
28  for (let i = 0; i < c.length; i++) {
29    assert.strictEqual(c[i], b[i]);
30  }
31}
32
33{
34  // Floats will be converted to integers via `Math.floor`
35  b.fill(++cntr);
36  c.fill(++cntr);
37  const copied = b.copy(c, 0, 0, 512.5);
38  assert.strictEqual(copied, 512);
39  for (let i = 0; i < c.length; i++) {
40    assert.strictEqual(c[i], b[i]);
41  }
42}
43
44{
45  // Copy c into b, without specifying sourceEnd
46  b.fill(++cntr);
47  c.fill(++cntr);
48  const copied = c.copy(b, 0, 0);
49  assert.strictEqual(copied, c.length);
50  for (let i = 0; i < c.length; i++) {
51    assert.strictEqual(b[i], c[i]);
52  }
53}
54
55{
56  // Copy c into b, without specifying sourceStart
57  b.fill(++cntr);
58  c.fill(++cntr);
59  const copied = c.copy(b, 0);
60  assert.strictEqual(copied, c.length);
61  for (let i = 0; i < c.length; i++) {
62    assert.strictEqual(b[i], c[i]);
63  }
64}
65
66{
67  // Copied source range greater than source length
68  b.fill(++cntr);
69  c.fill(++cntr);
70  const copied = c.copy(b, 0, 0, c.length + 1);
71  assert.strictEqual(copied, c.length);
72  for (let i = 0; i < c.length; i++) {
73    assert.strictEqual(b[i], c[i]);
74  }
75}
76
77{
78  // Copy longer buffer b to shorter c without targetStart
79  b.fill(++cntr);
80  c.fill(++cntr);
81  const copied = b.copy(c);
82  assert.strictEqual(copied, c.length);
83  for (let i = 0; i < c.length; i++) {
84    assert.strictEqual(c[i], b[i]);
85  }
86}
87
88{
89  // Copy starting near end of b to c
90  b.fill(++cntr);
91  c.fill(++cntr);
92  const copied = b.copy(c, 0, b.length - Math.floor(c.length / 2));
93  assert.strictEqual(copied, Math.floor(c.length / 2));
94  for (let i = 0; i < Math.floor(c.length / 2); i++) {
95    assert.strictEqual(c[i], b[b.length - Math.floor(c.length / 2) + i]);
96  }
97  for (let i = Math.floor(c.length / 2) + 1; i < c.length; i++) {
98    assert.strictEqual(c[c.length - 1], c[i]);
99  }
100}
101
102{
103  // Try to copy 513 bytes, and check we don't overrun c
104  b.fill(++cntr);
105  c.fill(++cntr);
106  const copied = b.copy(c, 0, 0, 513);
107  assert.strictEqual(copied, c.length);
108  for (let i = 0; i < c.length; i++) {
109    assert.strictEqual(c[i], b[i]);
110  }
111}
112
113{
114  // copy 768 bytes from b into b
115  b.fill(++cntr);
116  b.fill(++cntr, 256);
117  const copied = b.copy(b, 0, 256, 1024);
118  assert.strictEqual(copied, 768);
119  for (let i = 0; i < b.length; i++) {
120    assert.strictEqual(b[i], cntr);
121  }
122}
123
124// Copy string longer than buffer length (failure will segfault)
125const bb = Buffer.allocUnsafe(10);
126bb.fill('hello crazy world');
127
128
129// Try to copy from before the beginning of b. Should not throw.
130b.copy(c, 0, 100, 10);
131
132// Throw with invalid source type
133assert.throws(
134  () => Buffer.prototype.copy.call(0),
135  {
136    code: 'ERR_INVALID_ARG_TYPE',
137    name: 'TypeError',
138  }
139);
140
141// Copy throws at negative targetStart
142assert.throws(
143  () => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), -1, 0),
144  {
145    code: 'ERR_OUT_OF_RANGE',
146    name: 'RangeError',
147    message: 'The value of "targetStart" is out of range. ' +
148             'It must be >= 0. Received -1'
149  }
150);
151
152// Copy throws at negative sourceStart
153assert.throws(
154  () => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, -1),
155  {
156    code: 'ERR_OUT_OF_RANGE',
157    name: 'RangeError',
158  }
159);
160
161// Copy throws if sourceStart is greater than length of source
162assert.throws(
163  () => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, 100),
164  {
165    code: 'ERR_OUT_OF_RANGE',
166    name: 'RangeError',
167  }
168);
169
170{
171  // Check sourceEnd resets to targetEnd if former is greater than the latter
172  b.fill(++cntr);
173  c.fill(++cntr);
174  b.copy(c, 0, 0, 1025);
175  for (let i = 0; i < c.length; i++) {
176    assert.strictEqual(c[i], b[i]);
177  }
178}
179
180// Throw with negative sourceEnd
181assert.throws(
182  () => b.copy(c, 0, 0, -1),
183  {
184    code: 'ERR_OUT_OF_RANGE',
185    name: 'RangeError',
186    message: 'The value of "sourceEnd" is out of range. ' +
187             'It must be >= 0. Received -1'
188  }
189);
190
191// When sourceStart is greater than sourceEnd, zero copied
192assert.strictEqual(b.copy(c, 0, 100, 10), 0);
193
194// When targetStart > targetLength, zero copied
195assert.strictEqual(b.copy(c, 512, 0, 10), 0);
196
197// Test that the `target` can be a Uint8Array.
198{
199  const d = new Uint8Array(c);
200  // copy 512 bytes, from 0 to 512.
201  b.fill(++cntr);
202  d.fill(++cntr);
203  const copied = b.copy(d, 0, 0, 512);
204  assert.strictEqual(copied, 512);
205  for (let i = 0; i < d.length; i++) {
206    assert.strictEqual(d[i], b[i]);
207  }
208}
209
210// Test that the source can be a Uint8Array, too.
211{
212  const e = new Uint8Array(b);
213  // copy 512 bytes, from 0 to 512.
214  e.fill(++cntr);
215  c.fill(++cntr);
216  const copied = Buffer.prototype.copy.call(e, c, 0, 0, 512);
217  assert.strictEqual(copied, 512);
218  for (let i = 0; i < c.length; i++) {
219    assert.strictEqual(c[i], e[i]);
220  }
221}
222
223// https://github.com/nodejs/node/issues/23668: Do not crash for invalid input.
224c.fill('c');
225b.copy(c, 'not a valid offset');
226// Make sure this acted like a regular copy with `0` offset.
227assert.deepStrictEqual(c, b.slice(0, c.length));
228
229{
230  c.fill('C');
231  assert.throws(() => {
232    b.copy(c, { [Symbol.toPrimitive]() { throw new Error('foo'); } });
233  }, /foo/);
234  // No copying took place:
235  assert.deepStrictEqual(c.toString(), 'C'.repeat(c.length));
236}
237