tests.js
  1  /* eslint-disable node/no-deprecated-api */
  2  
  3  'use strict'
  4  
  5  var test = require('tape')
  6  
  7  var buffer = require('buffer')
  8  
  9  var index = require('./')
 10  var safer = require('./safer')
 11  var dangerous = require('./dangerous')
 12  
 13  /* Inheritance tests */
 14  
 15  test('Default is Safer', function (t) {
 16    t.equal(index, safer)
 17    t.notEqual(safer, dangerous)
 18    t.notEqual(index, dangerous)
 19    t.end()
 20  })
 21  
 22  test('Is not a function', function (t) {
 23    [index, safer, dangerous].forEach(function (impl) {
 24      t.equal(typeof impl, 'object')
 25      t.equal(typeof impl.Buffer, 'object')
 26    });
 27    [buffer].forEach(function (impl) {
 28      t.equal(typeof impl, 'object')
 29      t.equal(typeof impl.Buffer, 'function')
 30    })
 31    t.end()
 32  })
 33  
 34  test('Constructor throws', function (t) {
 35    [index, safer, dangerous].forEach(function (impl) {
 36      t.throws(function () { impl.Buffer() })
 37      t.throws(function () { impl.Buffer(0) })
 38      t.throws(function () { impl.Buffer('a') })
 39      t.throws(function () { impl.Buffer('a', 'utf-8') })
 40      t.throws(function () { return new impl.Buffer() })
 41      t.throws(function () { return new impl.Buffer(0) })
 42      t.throws(function () { return new impl.Buffer('a') })
 43      t.throws(function () { return new impl.Buffer('a', 'utf-8') })
 44    })
 45    t.end()
 46  })
 47  
 48  test('Safe methods exist', function (t) {
 49    [index, safer, dangerous].forEach(function (impl) {
 50      t.equal(typeof impl.Buffer.alloc, 'function', 'alloc')
 51      t.equal(typeof impl.Buffer.from, 'function', 'from')
 52    })
 53    t.end()
 54  })
 55  
 56  test('Unsafe methods exist only in Dangerous', function (t) {
 57    [index, safer].forEach(function (impl) {
 58      t.equal(typeof impl.Buffer.allocUnsafe, 'undefined')
 59      t.equal(typeof impl.Buffer.allocUnsafeSlow, 'undefined')
 60    });
 61    [dangerous].forEach(function (impl) {
 62      t.equal(typeof impl.Buffer.allocUnsafe, 'function')
 63      t.equal(typeof impl.Buffer.allocUnsafeSlow, 'function')
 64    })
 65    t.end()
 66  })
 67  
 68  test('Generic methods/properties are defined and equal', function (t) {
 69    ['poolSize', 'isBuffer', 'concat', 'byteLength'].forEach(function (method) {
 70      [index, safer, dangerous].forEach(function (impl) {
 71        t.equal(impl.Buffer[method], buffer.Buffer[method], method)
 72        t.notEqual(typeof impl.Buffer[method], 'undefined', method)
 73      })
 74    })
 75    t.end()
 76  })
 77  
 78  test('Built-in buffer static methods/properties are inherited', function (t) {
 79    Object.keys(buffer).forEach(function (method) {
 80      if (method === 'SlowBuffer' || method === 'Buffer') return;
 81      [index, safer, dangerous].forEach(function (impl) {
 82        t.equal(impl[method], buffer[method], method)
 83        t.notEqual(typeof impl[method], 'undefined', method)
 84      })
 85    })
 86    t.end()
 87  })
 88  
 89  test('Built-in Buffer static methods/properties are inherited', function (t) {
 90    Object.keys(buffer.Buffer).forEach(function (method) {
 91      if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return;
 92      [index, safer, dangerous].forEach(function (impl) {
 93        t.equal(impl.Buffer[method], buffer.Buffer[method], method)
 94        t.notEqual(typeof impl.Buffer[method], 'undefined', method)
 95      })
 96    })
 97    t.end()
 98  })
 99  
100  test('.prototype property of Buffer is inherited', function (t) {
101    [index, safer, dangerous].forEach(function (impl) {
102      t.equal(impl.Buffer.prototype, buffer.Buffer.prototype, 'prototype')
103      t.notEqual(typeof impl.Buffer.prototype, 'undefined', 'prototype')
104    })
105    t.end()
106  })
107  
108  test('All Safer methods are present in Dangerous', function (t) {
109    Object.keys(safer).forEach(function (method) {
110      if (method === 'Buffer') return;
111      [index, safer, dangerous].forEach(function (impl) {
112        t.equal(impl[method], safer[method], method)
113        if (method !== 'kStringMaxLength') {
114          t.notEqual(typeof impl[method], 'undefined', method)
115        }
116      })
117    })
118    Object.keys(safer.Buffer).forEach(function (method) {
119      [index, safer, dangerous].forEach(function (impl) {
120        t.equal(impl.Buffer[method], safer.Buffer[method], method)
121        t.notEqual(typeof impl.Buffer[method], 'undefined', method)
122      })
123    })
124    t.end()
125  })
126  
127  test('Safe methods from Dangerous methods are present in Safer', function (t) {
128    Object.keys(dangerous).forEach(function (method) {
129      if (method === 'Buffer') return;
130      [index, safer, dangerous].forEach(function (impl) {
131        t.equal(impl[method], dangerous[method], method)
132        if (method !== 'kStringMaxLength') {
133          t.notEqual(typeof impl[method], 'undefined', method)
134        }
135      })
136    })
137    Object.keys(dangerous.Buffer).forEach(function (method) {
138      if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return;
139      [index, safer, dangerous].forEach(function (impl) {
140        t.equal(impl.Buffer[method], dangerous.Buffer[method], method)
141        t.notEqual(typeof impl.Buffer[method], 'undefined', method)
142      })
143    })
144    t.end()
145  })
146  
147  /* Behaviour tests */
148  
149  test('Methods return Buffers', function (t) {
150    [index, safer, dangerous].forEach(function (impl) {
151      t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0)))
152      t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 10)))
153      t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 'a')))
154      t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10)))
155      t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10, 'x')))
156      t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(9, 'ab')))
157      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('')))
158      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string')))
159      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string', 'utf-8')))
160      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64')))
161      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([0, 42, 3])))
162      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(new Uint8Array([0, 42, 3]))))
163      t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([])))
164    });
165    ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) {
166      t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](0)))
167      t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](10)))
168    })
169    t.end()
170  })
171  
172  test('Constructor is buffer.Buffer', function (t) {
173    [index, safer, dangerous].forEach(function (impl) {
174      t.equal(impl.Buffer.alloc(0).constructor, buffer.Buffer)
175      t.equal(impl.Buffer.alloc(0, 10).constructor, buffer.Buffer)
176      t.equal(impl.Buffer.alloc(0, 'a').constructor, buffer.Buffer)
177      t.equal(impl.Buffer.alloc(10).constructor, buffer.Buffer)
178      t.equal(impl.Buffer.alloc(10, 'x').constructor, buffer.Buffer)
179      t.equal(impl.Buffer.alloc(9, 'ab').constructor, buffer.Buffer)
180      t.equal(impl.Buffer.from('').constructor, buffer.Buffer)
181      t.equal(impl.Buffer.from('string').constructor, buffer.Buffer)
182      t.equal(impl.Buffer.from('string', 'utf-8').constructor, buffer.Buffer)
183      t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').constructor, buffer.Buffer)
184      t.equal(impl.Buffer.from([0, 42, 3]).constructor, buffer.Buffer)
185      t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).constructor, buffer.Buffer)
186      t.equal(impl.Buffer.from([]).constructor, buffer.Buffer)
187    });
188    [0, 10, 100].forEach(function (arg) {
189      t.equal(dangerous.Buffer.allocUnsafe(arg).constructor, buffer.Buffer)
190      t.equal(dangerous.Buffer.allocUnsafeSlow(arg).constructor, buffer.SlowBuffer(0).constructor)
191    })
192    t.end()
193  })
194  
195  test('Invalid calls throw', function (t) {
196    [index, safer, dangerous].forEach(function (impl) {
197      t.throws(function () { impl.Buffer.from(0) })
198      t.throws(function () { impl.Buffer.from(10) })
199      t.throws(function () { impl.Buffer.from(10, 'utf-8') })
200      t.throws(function () { impl.Buffer.from('string', 'invalid encoding') })
201      t.throws(function () { impl.Buffer.from(-10) })
202      t.throws(function () { impl.Buffer.from(1e90) })
203      t.throws(function () { impl.Buffer.from(Infinity) })
204      t.throws(function () { impl.Buffer.from(-Infinity) })
205      t.throws(function () { impl.Buffer.from(NaN) })
206      t.throws(function () { impl.Buffer.from(null) })
207      t.throws(function () { impl.Buffer.from(undefined) })
208      t.throws(function () { impl.Buffer.from() })
209      t.throws(function () { impl.Buffer.from({}) })
210      t.throws(function () { impl.Buffer.alloc('') })
211      t.throws(function () { impl.Buffer.alloc('string') })
212      t.throws(function () { impl.Buffer.alloc('string', 'utf-8') })
213      t.throws(function () { impl.Buffer.alloc('b25ldHdvdGhyZWU=', 'base64') })
214      t.throws(function () { impl.Buffer.alloc(-10) })
215      t.throws(function () { impl.Buffer.alloc(1e90) })
216      t.throws(function () { impl.Buffer.alloc(2 * (1 << 30)) })
217      t.throws(function () { impl.Buffer.alloc(Infinity) })
218      t.throws(function () { impl.Buffer.alloc(-Infinity) })
219      t.throws(function () { impl.Buffer.alloc(null) })
220      t.throws(function () { impl.Buffer.alloc(undefined) })
221      t.throws(function () { impl.Buffer.alloc() })
222      t.throws(function () { impl.Buffer.alloc([]) })
223      t.throws(function () { impl.Buffer.alloc([0, 42, 3]) })
224      t.throws(function () { impl.Buffer.alloc({}) })
225    });
226    ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) {
227      t.throws(function () { dangerous.Buffer[method]('') })
228      t.throws(function () { dangerous.Buffer[method]('string') })
229      t.throws(function () { dangerous.Buffer[method]('string', 'utf-8') })
230      t.throws(function () { dangerous.Buffer[method](2 * (1 << 30)) })
231      t.throws(function () { dangerous.Buffer[method](Infinity) })
232      if (dangerous.Buffer[method] === buffer.Buffer.allocUnsafe) {
233        t.skip('Skipping, older impl of allocUnsafe coerced negative sizes to 0')
234      } else {
235        t.throws(function () { dangerous.Buffer[method](-10) })
236        t.throws(function () { dangerous.Buffer[method](-1e90) })
237        t.throws(function () { dangerous.Buffer[method](-Infinity) })
238      }
239      t.throws(function () { dangerous.Buffer[method](null) })
240      t.throws(function () { dangerous.Buffer[method](undefined) })
241      t.throws(function () { dangerous.Buffer[method]() })
242      t.throws(function () { dangerous.Buffer[method]([]) })
243      t.throws(function () { dangerous.Buffer[method]([0, 42, 3]) })
244      t.throws(function () { dangerous.Buffer[method]({}) })
245    })
246    t.end()
247  })
248  
249  test('Buffers have appropriate lengths', function (t) {
250    [index, safer, dangerous].forEach(function (impl) {
251      t.equal(impl.Buffer.alloc(0).length, 0)
252      t.equal(impl.Buffer.alloc(10).length, 10)
253      t.equal(impl.Buffer.from('').length, 0)
254      t.equal(impl.Buffer.from('string').length, 6)
255      t.equal(impl.Buffer.from('string', 'utf-8').length, 6)
256      t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').length, 11)
257      t.equal(impl.Buffer.from([0, 42, 3]).length, 3)
258      t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).length, 3)
259      t.equal(impl.Buffer.from([]).length, 0)
260    });
261    ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) {
262      t.equal(dangerous.Buffer[method](0).length, 0)
263      t.equal(dangerous.Buffer[method](10).length, 10)
264    })
265    t.end()
266  })
267  
268  test('Buffers have appropriate lengths (2)', function (t) {
269    t.equal(index.Buffer.alloc, safer.Buffer.alloc)
270    t.equal(index.Buffer.alloc, dangerous.Buffer.alloc)
271    var ok = true;
272    [ safer.Buffer.alloc,
273      dangerous.Buffer.allocUnsafe,
274      dangerous.Buffer.allocUnsafeSlow
275    ].forEach(function (method) {
276      for (var i = 0; i < 1e2; i++) {
277        var length = Math.round(Math.random() * 1e5)
278        var buf = method(length)
279        if (!buffer.Buffer.isBuffer(buf)) ok = false
280        if (buf.length !== length) ok = false
281      }
282    })
283    t.ok(ok)
284    t.end()
285  })
286  
287  test('.alloc(size) is zero-filled and has correct length', function (t) {
288    t.equal(index.Buffer.alloc, safer.Buffer.alloc)
289    t.equal(index.Buffer.alloc, dangerous.Buffer.alloc)
290    var ok = true
291    for (var i = 0; i < 1e2; i++) {
292      var length = Math.round(Math.random() * 2e6)
293      var buf = index.Buffer.alloc(length)
294      if (!buffer.Buffer.isBuffer(buf)) ok = false
295      if (buf.length !== length) ok = false
296      var j
297      for (j = 0; j < length; j++) {
298        if (buf[j] !== 0) ok = false
299      }
300      buf.fill(1)
301      for (j = 0; j < length; j++) {
302        if (buf[j] !== 1) ok = false
303      }
304    }
305    t.ok(ok)
306    t.end()
307  })
308  
309  test('.allocUnsafe / .allocUnsafeSlow are fillable and have correct lengths', function (t) {
310    ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) {
311      var ok = true
312      for (var i = 0; i < 1e2; i++) {
313        var length = Math.round(Math.random() * 2e6)
314        var buf = dangerous.Buffer[method](length)
315        if (!buffer.Buffer.isBuffer(buf)) ok = false
316        if (buf.length !== length) ok = false
317        buf.fill(0, 0, length)
318        var j
319        for (j = 0; j < length; j++) {
320          if (buf[j] !== 0) ok = false
321        }
322        buf.fill(1, 0, length)
323        for (j = 0; j < length; j++) {
324          if (buf[j] !== 1) ok = false
325        }
326      }
327      t.ok(ok, method)
328    })
329    t.end()
330  })
331  
332  test('.alloc(size, fill) is `fill`-filled', function (t) {
333    t.equal(index.Buffer.alloc, safer.Buffer.alloc)
334    t.equal(index.Buffer.alloc, dangerous.Buffer.alloc)
335    var ok = true
336    for (var i = 0; i < 1e2; i++) {
337      var length = Math.round(Math.random() * 2e6)
338      var fill = Math.round(Math.random() * 255)
339      var buf = index.Buffer.alloc(length, fill)
340      if (!buffer.Buffer.isBuffer(buf)) ok = false
341      if (buf.length !== length) ok = false
342      for (var j = 0; j < length; j++) {
343        if (buf[j] !== fill) ok = false
344      }
345    }
346    t.ok(ok)
347    t.end()
348  })
349  
350  test('.alloc(size, fill) is `fill`-filled', function (t) {
351    t.equal(index.Buffer.alloc, safer.Buffer.alloc)
352    t.equal(index.Buffer.alloc, dangerous.Buffer.alloc)
353    var ok = true
354    for (var i = 0; i < 1e2; i++) {
355      var length = Math.round(Math.random() * 2e6)
356      var fill = Math.round(Math.random() * 255)
357      var buf = index.Buffer.alloc(length, fill)
358      if (!buffer.Buffer.isBuffer(buf)) ok = false
359      if (buf.length !== length) ok = false
360      for (var j = 0; j < length; j++) {
361        if (buf[j] !== fill) ok = false
362      }
363    }
364    t.ok(ok)
365    t.deepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 97))
366    t.notDeepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 98))
367  
368    var tmp = new buffer.Buffer(2)
369    tmp.fill('ok')
370    if (tmp[1] === tmp[0]) {
371      // Outdated Node.js
372      t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('ooooo'))
373    } else {
374      t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('okoko'))
375    }
376    t.notDeepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('kokok'))
377  
378    t.end()
379  })
380  
381  test('safer.Buffer.from returns results same as Buffer constructor', function (t) {
382    [index, safer, dangerous].forEach(function (impl) {
383      t.deepEqual(impl.Buffer.from(''), new buffer.Buffer(''))
384      t.deepEqual(impl.Buffer.from('string'), new buffer.Buffer('string'))
385      t.deepEqual(impl.Buffer.from('string', 'utf-8'), new buffer.Buffer('string', 'utf-8'))
386      t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), new buffer.Buffer('b25ldHdvdGhyZWU=', 'base64'))
387      t.deepEqual(impl.Buffer.from([0, 42, 3]), new buffer.Buffer([0, 42, 3]))
388      t.deepEqual(impl.Buffer.from(new Uint8Array([0, 42, 3])), new buffer.Buffer(new Uint8Array([0, 42, 3])))
389      t.deepEqual(impl.Buffer.from([]), new buffer.Buffer([]))
390    })
391    t.end()
392  })
393  
394  test('safer.Buffer.from returns consistent results', function (t) {
395    [index, safer, dangerous].forEach(function (impl) {
396      t.deepEqual(impl.Buffer.from(''), impl.Buffer.alloc(0))
397      t.deepEqual(impl.Buffer.from([]), impl.Buffer.alloc(0))
398      t.deepEqual(impl.Buffer.from(new Uint8Array([])), impl.Buffer.alloc(0))
399      t.deepEqual(impl.Buffer.from('string', 'utf-8'), impl.Buffer.from('string'))
400      t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from([115, 116, 114, 105, 110, 103]))
401      t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from(impl.Buffer.from('string')))
402      t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), impl.Buffer.from('onetwothree'))
403      t.notDeepEqual(impl.Buffer.from('b25ldHdvdGhyZWU='), impl.Buffer.from('onetwothree'))
404    })
405    t.end()
406  })