@@ -22,23 +22,14 @@ import { concatBuffers } from '../src/concat_buffers'
2222import { Buffer } from 'buffer'
2323import * as fixtures from './fixtures'
2424
25- describe ( 'readElements' , ( ) => {
26- it ( 'should be able to find one element' , ( ) => {
27- const len = Buffer . alloc ( 2 )
28- len . writeUInt16BE ( 4 , 0 )
29- const data = new Uint8Array ( [ ...Buffer . from ( 'data' ) ] )
30- const buff = concatBuffers ( len , data )
31- const info = readElements ( 1 , buff , 0 )
32- if ( info === false ) throw new Error ( 'Fail' )
33- expect ( info . elements ) . to . be . instanceof ( Array )
34- expect ( info . elements . length ) . to . eql ( 1 )
35- expect ( info . elements [ 0 ] ) . to . deep . equal ( data )
36- expect ( info . readPos ) . to . eql ( 6 )
37- } )
25+ function randomNat ( limit : number ) : number {
26+ return Math . floor ( Math . random ( ) * limit )
27+ }
3828
39- it ( 'should be able to handle multiple elements' , ( ) => {
29+ describe ( 'readElements' , ( ) => {
30+ it ( 'should be able to handle multiple elements containing multiple fields without padding' , ( ) => {
4031 const utf8DataStrings = [
41- 'some utf8 information' , '\u00bd + \u00bc = \u00be' , 'to encode '
32+ 'here' , 'is' , ' some' , ' utf8' , ' information', '\u00bd + \u00bc = \u00be'
4233 ]
4334 const buffData = utf8DataStrings . map ( str => new Uint8Array ( [ ...Buffer . from ( str ) ] ) )
4435 const buff = concatBuffers ( ...buffData . map ( bufStr => {
@@ -47,75 +38,93 @@ describe('readElements', () => {
4738 return concatBuffers ( len , bufStr )
4839 } ) )
4940
50- const info = readElements ( 3 , buff , 0 )
51-
52- if ( info === false ) throw new Error ( 'Fail' )
53- expect ( info . elements ) . to . be . instanceof ( Array )
54- expect ( info . elements . length ) . to . eql ( 3 )
55- expect ( info . elements [ 0 ] ) . to . deep . equal ( buffData [ 0 ] )
56- expect ( info . elements [ 1 ] ) . to . deep . equal ( buffData [ 1 ] )
57- expect ( info . elements [ 2 ] ) . to . deep . equal ( buffData [ 2 ] )
58- expect ( Buffer . from ( info . elements [ 0 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 0 ] )
59- expect ( Buffer . from ( info . elements [ 1 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 1 ] )
60- expect ( Buffer . from ( info . elements [ 2 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 2 ] )
61- expect ( info . readPos ) . to . eql ( 48 )
41+ /* The elements in the buffer can be arranged in several ways.
42+ * For example, we can think of them as six elements with one
43+ * field each, or as three elements with two fields each.
44+ */
45+ const dimensions = [ [ 1 , 6 ] , [ 2 , 3 ] , [ 3 , 2 ] , [ 6 , 1 ] ]
46+
47+ dimensions . map ( ( [ elementCount , fieldsPerElement ] ) => {
48+ const info = readElements ( elementCount , fieldsPerElement , buff )
49+
50+ if ( info === false ) throw new Error ( 'Fail' )
51+ let elements = info . elements
52+ expect ( elements ) . to . be . instanceof ( Array )
53+ expect ( elements . length ) . to . eql ( elementCount )
54+
55+ for ( let eCount = 0 ; eCount < elementCount ; eCount ++ ) {
56+ let element = info . elements [ eCount ]
57+ expect ( element ) . to . be . instanceof ( Array )
58+ expect ( element . length ) . to . eql ( fieldsPerElement )
59+ for ( let fCount = 0 ; fCount < fieldsPerElement ; fCount ++ ) {
60+ let field = element [ fCount ]
61+ expect ( field ) . to . deep . equal ( buffData [ eCount * fieldsPerElement + fCount ] )
62+ expect ( Buffer . from ( field ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ eCount * fieldsPerElement + fCount ] )
63+ }
64+ }
65+
66+ expect ( info . readPos ) . to . eql ( buff . byteLength )
67+ } )
6268 } )
6369
64- it ( 'should be able to handle multiple elements when not reading from the beginning ' , ( ) => {
65- const utf8DataStrings = [
66- 'some utf8 information' , '\u00bd + \u00bc = \u00be' , 'to encode'
67- ]
70+ it ( 'should be able to handle multiple elements containing multiple fields with various padding ' , ( ) => {
71+ let numberOfRuns = 16
72+ const maxPaddingLength = 1024
73+ const utf8DataStrings = [ 'here' , 'is' , 'some' , 'utf8' , 'information' , '\u00bd + \u00bc = \u00be' ]
6874 const buffData = utf8DataStrings . map ( str => new Uint8Array ( [ ...Buffer . from ( str ) ] ) )
69- const padding = Buffer . alloc ( 10 )
70- const buff = concatBuffers ( padding , ...buffData . map ( bufStr => {
75+ const mainBuffer = concatBuffers ( ...buffData . map ( bufStr => {
7176 const len = Buffer . alloc ( 2 )
7277 len . writeUInt16BE ( bufStr . byteLength , 0 )
7378 return concatBuffers ( len , bufStr )
7479 } ) )
7580
76- const info = readElements ( 3 , buff , padding . length )
77-
78- if ( info === false ) throw new Error ( 'Fail' )
79- expect ( info . elements ) . to . be . instanceof ( Array )
80- expect ( info . elements . length ) . to . eql ( 3 )
81- expect ( info . elements [ 0 ] ) . to . deep . equal ( buffData [ 0 ] )
82- expect ( info . elements [ 1 ] ) . to . deep . equal ( buffData [ 1 ] )
83- expect ( info . elements [ 2 ] ) . to . deep . equal ( buffData [ 2 ] )
84- expect ( Buffer . from ( info . elements [ 0 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 0 ] )
85- expect ( Buffer . from ( info . elements [ 1 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 1 ] )
86- expect ( Buffer . from ( info . elements [ 2 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 2 ] )
87- expect ( info . readPos ) . to . eql ( 58 )
81+ const dimensions = [ [ 1 , 6 ] , [ 2 , 3 ] , [ 3 , 2 ] , [ 6 , 1 ] ]
82+
83+ while ( numberOfRuns -- ) {
84+ let leftPadding = Buffer . alloc ( randomNat ( maxPaddingLength ) )
85+ let rightPadding = Buffer . alloc ( randomNat ( maxPaddingLength ) )
86+ let buff = concatBuffers ( leftPadding , mainBuffer , rightPadding )
87+
88+ dimensions . map ( ( [ elementCount , fieldsPerElement ] ) => {
89+ const info = readElements ( elementCount , fieldsPerElement , buff , leftPadding . byteLength )
90+
91+ if ( info === false ) throw new Error ( 'Fail' )
92+ let elements = info . elements
93+ expect ( elements ) . to . be . instanceof ( Array )
94+ expect ( elements . length ) . to . eql ( elementCount )
95+
96+ for ( let eCount = 0 ; eCount < elementCount ; eCount ++ ) {
97+ let element = info . elements [ eCount ]
98+ expect ( element ) . to . be . instanceof ( Array )
99+ expect ( element . length ) . to . eql ( fieldsPerElement )
100+ for ( let fCount = 0 ; fCount < fieldsPerElement ; fCount ++ ) {
101+ let field = element [ fCount ]
102+ expect ( field ) . to . deep . equal ( buffData [ eCount * fieldsPerElement + fCount ] )
103+ expect ( Buffer . from ( field ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ eCount * fieldsPerElement + fCount ] )
104+ }
105+ }
106+
107+ expect ( info . readPos ) . to . eql ( leftPadding . byteLength + mainBuffer . byteLength )
108+ } )
109+ }
88110 } )
89111
90- it ( 'should be able to handle multiple elements with padding on both sides' , ( ) => {
91- const utf8DataStrings = [
92- 'some utf8 information' , '\u00bd + \u00bc = \u00be' , 'to encode'
93- ]
94- const buffData = utf8DataStrings . map ( str => new Uint8Array ( [ ...Buffer . from ( str ) ] ) )
95- const padding = Buffer . alloc ( 10 )
96- const buff = concatBuffers ( padding , ...buffData . map ( bufStr => {
97- const len = Buffer . alloc ( 2 )
98- len . writeUInt16BE ( bufStr . byteLength , 0 )
99- return concatBuffers ( len , bufStr )
100- } ) , padding )
101-
102- const info = readElements ( 3 , buff , padding . length )
103-
104- if ( info === false ) throw new Error ( 'Fail' )
105- expect ( info . elements ) . to . be . instanceof ( Array )
106- expect ( info . elements . length ) . to . eql ( 3 )
107- expect ( info . elements [ 0 ] ) . to . deep . equal ( buffData [ 0 ] )
108- expect ( info . elements [ 1 ] ) . to . deep . equal ( buffData [ 1 ] )
109- expect ( info . elements [ 2 ] ) . to . deep . equal ( buffData [ 2 ] )
110- expect ( Buffer . from ( info . elements [ 0 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 0 ] )
111- expect ( Buffer . from ( info . elements [ 1 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 1 ] )
112- expect ( Buffer . from ( info . elements [ 2 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 2 ] )
113- expect ( info . readPos ) . to . eql ( 58 )
112+ it ( 'Precondition: readPos must be non-negative and within the byte length of the buffer given.' , ( ) => {
113+ const buff = new Uint8Array ( 32 )
114+ const readPosBeyondBuff = buff . byteLength + 1
115+ expect ( ( ) => readElements ( 1 , 1 , buff , readPosBeyondBuff ) ) . to . throw ( )
116+ } )
117+
118+ it ( 'Precondition: elementCount and fieldsPerElement must be non-negative.' , ( ) => {
119+ const buff = new Uint8Array ( 32 )
120+ expect ( ( ) => readElements ( - 1 , 1 , buff ) ) . to . throw ( )
121+ expect ( ( ) => readElements ( 1 , - 1 , buff ) ) . to . throw ( )
122+ expect ( ( ) => readElements ( - 1 , - 1 , buff ) ) . to . throw ( )
114123 } )
115124
116125 it ( 'Check for early return (Postcondition): Enough data must exist to read the Uint16 length value.; Check for early return (Postcondition): Enough data must exist length of the value.' , ( ) => {
117126 const utf8DataStrings = [
118- 'some utf8 information' , '\u00bd + \u00bc = \u00be' , 'to encode '
127+ 'here' , 'is' , ' some' , ' utf8' , ' information', '\u00bd + \u00bc = \u00be'
119128 ]
120129 const buffData = utf8DataStrings . map ( str => new Uint8Array ( [ ...Buffer . from ( str ) ] ) )
121130 const buff = concatBuffers ( ...buffData . map ( bufStr => {
@@ -124,35 +133,13 @@ describe('readElements', () => {
124133 return concatBuffers ( len , bufStr )
125134 } ) )
126135
127- // By testing every combination of byte length possible
128- // Both loop invariants are covered.
129- for ( let i = 0 ; buff . byteLength > i ; i ++ ) {
130- const info = readElements ( 3 , buff . slice ( 0 , i ) , 0 )
131- expect ( info ) . to . eql ( false )
132- }
133- // Engage pedantry...
134- const info = readElements ( 3 , buff . slice ( 0 , buff . byteLength ) , 0 )
135- if ( info === false ) throw new Error ( 'Fail' )
136- expect ( info . elements ) . to . be . instanceof ( Array )
137- expect ( info . elements . length ) . to . eql ( 3 )
138- expect ( info . elements [ 0 ] ) . to . deep . equal ( buffData [ 0 ] )
139- expect ( info . elements [ 1 ] ) . to . deep . equal ( buffData [ 1 ] )
140- expect ( info . elements [ 2 ] ) . to . deep . equal ( buffData [ 2 ] )
141- expect ( Buffer . from ( info . elements [ 0 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 0 ] )
142- expect ( Buffer . from ( info . elements [ 1 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 1 ] )
143- expect ( Buffer . from ( info . elements [ 2 ] ) . toString ( ) ) . to . deep . equal ( utf8DataStrings [ 2 ] )
144- expect ( info . readPos ) . to . eql ( 48 )
145- } )
146-
147- it ( 'Precondition: readElements readPos must be within the byte length of the buffer given.' , ( ) => {
148- const buff = new Uint8Array ( 32 )
149- const readPosBeyondBuff = buff . byteLength + 1
150- expect ( ( ) => readElements ( 1 , buff , readPosBeyondBuff ) ) . to . throw ( )
151- } )
136+ /* Will return false when trying to read the length of the seventh element */
137+ const infoFalse1 = readElements ( 1 , 7 , buff )
138+ expect ( infoFalse1 ) . to . equal ( false )
152139
153- it ( 'Precondition: elementCount must not be negative.' , ( ) => {
154- const buff = new Uint8Array ( 32 )
155- expect ( ( ) => readElements ( - 1 , buff ) ) . to . throw ( )
140+ /* Will return false when trying to read the sixth element */
141+ const infoFalse2 = readElements ( 1 , 6 , buff . slice ( 0 , buff . byteLength - 1 ) )
142+ expect ( infoFalse2 ) . to . equal ( false )
156143 } )
157144
158145 it ( 'ArrayBuffer for a Uint8Array or Buffer may be larger than the Uint8Array or Buffer that it is a view over is.' , ( ) => {
@@ -162,12 +149,12 @@ describe('readElements', () => {
162149 * read position past the length and count should succeed.
163150 */
164151 const buff = fixtures . basicEncryptionContext ( )
165- expect ( readElements ( 4 , buff , 0 ) ) . to . equal ( false )
166- expect ( readElements ( 4 , buff , 4 ) ) . to . not . equal ( false )
152+ expect ( readElements ( 4 , 1 , buff , 0 ) ) . to . equal ( false )
153+ expect ( readElements ( 4 , 1 , buff , 4 ) ) . to . not . equal ( false )
167154 /* Given this I can use this to construct a new view of part of the
168155 * ArrayBuffer to simulate a large ArrayBuffer that is sliced
169156 * into parts for efficiency. */
170157 const sharingArrayBuffer = new Uint8Array ( buff . buffer , 4 , buff . byteLength - 4 )
171- expect ( readElements ( 4 , sharingArrayBuffer ) ) . to . not . equal ( false )
158+ expect ( readElements ( 4 , 1 , sharingArrayBuffer ) ) . to . not . equal ( false )
172159 } )
173160} )
0 commit comments