From 2ed482879f9032543fc585910944848a53b96bb4 Mon Sep 17 00:00:00 2001 From: Jeff Schiller Date: Mon, 20 Nov 2023 22:44:41 -0800 Subject: [PATCH] Beef up unit test coverage in io package. --- io/bitbuffer.js | 4 +-- io/bytebuffer.js | 2 +- package-lock.json | 18 +++++------ package.json | 5 ++-- tests/io-bitbuffer.spec.js | 60 ++++++++++++++++++++++++++++++++++++- tests/io-bitstream.spec.js | 30 +++++++++++++++++-- tests/io-bytebuffer.spec.js | 41 ++++++++++++++++++++----- tests/io-bytestream.spec.js | 29 ++++++++++++++++++ 8 files changed, 164 insertions(+), 25 deletions(-) diff --git a/io/bitbuffer.js b/io/bitbuffer.js index 6ea5c15..d445363 100644 --- a/io/bitbuffer.js +++ b/io/bitbuffer.js @@ -84,13 +84,13 @@ export class BitBuffer { if (this.bytePtr >= this.data.byteLength) { throw `No more bytes left when switching packing direction`; } - this.bitPtr = 7; + this.bitPtr = 0; } else if (!this.mtl && this.bitPtr !== 0) { this.bytePtr++; if (this.bytePtr >= this.data.byteLength) { throw `No more bytes left when switching packing direction`; } - this.bitPtr = 0; + this.bitPtr = 7; } } diff --git a/io/bytebuffer.js b/io/bytebuffer.js index 1d62844..3533176 100644 --- a/io/bytebuffer.js +++ b/io/bytebuffer.js @@ -114,7 +114,7 @@ export class ByteBuffer { writeASCIIString(str) { for (let i = 0; i < str.length; ++i) { const curByte = str.charCodeAt(i); - if (curByte < 0 || curByte > 255) { + if (curByte < 0 || curByte > 127) { throw 'Trying to write a non-ASCII string!'; } this.insertByte(curByte); diff --git a/package-lock.json b/package-lock.json index 256b9fc..d5d2227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@codedread/bitjs", - "version": "1.1.4", + "version": "1.1.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@codedread/bitjs", - "version": "1.1.4", + "version": "1.1.6", "license": "MIT", "devDependencies": { - "c8": "^7.12.0", + "c8": "^7.14.0", "chai": "^4.3.4", "mocha": "^10.1.0", "typescript": "^4.8.0" @@ -156,9 +156,9 @@ "dev": true }, "node_modules/c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", + "integrity": "sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", @@ -1520,9 +1520,9 @@ "dev": true }, "c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", + "integrity": "sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", diff --git a/package.json b/package.json index e3283e4..ebeaef2 100644 --- a/package.json +++ b/package.json @@ -33,9 +33,8 @@ "bugs": { "url": "https://github.com/codedread/bitjs/issues" }, - "dependencies": {}, "devDependencies": { - "c8": "^7.12.0", + "c8": "^7.14.0", "chai": "^4.3.4", "mocha": "^10.1.0", "typescript": "^4.8.0" @@ -46,7 +45,7 @@ }, "scripts": { "build-webpshim": "cd build; make", - "coverage": "./node_modules/.bin/c8 npm test", + "coverage": "c8 npm run test", "test": "./node_modules/.bin/mocha tests/*.spec.js", "update-types": "tsc" } diff --git a/tests/io-bitbuffer.spec.js b/tests/io-bitbuffer.spec.js index ba5c8fb..295e24f 100644 --- a/tests/io-bitbuffer.spec.js +++ b/tests/io-bitbuffer.spec.js @@ -11,18 +11,35 @@ import 'mocha'; import { expect } from 'chai'; describe('bitjs.io.BitBuffer', () => { + /** @type {BitBuffer} */ let buffer; + it('throws when invalid numBytes', () => { + expect(() => new BitBuffer()).throws(); + }); + describe('least-to-most-significant bit-packing', () => { beforeEach(() => { buffer = new BitBuffer(4); }); it('bit/byte pointers initialized properly', () => { + expect(buffer.getPackingDirection()).equals(false); expect(buffer.bytePtr).equals(0); expect(buffer.bitPtr).equals(0); - }) + }); + it('throws when writing invalid values', () => { + expect(() => buffer.writeBits(-3, 2)).throws(); + expect(() => buffer.writeBits(3, -2)).throws(); + expect(() => buffer.writeBits(0, 54)).throws(); + }); + + it('throws when writing too many bits into the buffer', () => { + buffer.writeBits(0, 31); // thirty-one zeroes. + expect(() => buffer.writeBits(1, 2)).throws(); + }); + it('write multiple bits', () => { buffer.writeBits(0b01011, 5); // Should result in: 0b00001011. expect(buffer.bytePtr).equals(0); @@ -47,6 +64,26 @@ describe('bitjs.io.BitBuffer', () => { expect(Array.from(buffer.data)).to.have.ordered.members( [0xfe, 0xff, 0x03, 0x00]); }); + + it('properly changes bit-packing direction', () => { + buffer.writeBits(3, 2); + expect(buffer.data[0]).equals(3); + expect(buffer.bytePtr).equals(0); + expect(buffer.bitPtr).equals(2); + + buffer.setPackingDirection(true /** most to least significant */); + expect(buffer.bytePtr).equals(1); + expect(buffer.bitPtr).equals(7); + + buffer.writeBits(7, 3); + expect(buffer.data[0]).equals(3); + expect(buffer.data[1]).equals(224); + }); + + it('throws when switching packing direction and no more bytes left', () => { + buffer.writeBits(0, 25); + expect(() => buffer.setPackingDirection(true)).throws(); + }); }); describe('most-to-least-significant bit-packing', () => { @@ -55,6 +92,7 @@ describe('bitjs.io.BitBuffer', () => { }); it('bit/byte pointers initialized properly', () => { + expect(buffer.getPackingDirection()).equals(true); expect(buffer.bytePtr).equals(0); expect(buffer.bitPtr).equals(7); }) @@ -84,5 +122,25 @@ describe('bitjs.io.BitBuffer', () => { expect(Array.from(buffer.data)).to.have.ordered.members( [0x7f, 0xff, 0xc0, 0x00]); }); + + it('properly changes bit-packing direction', () => { + buffer.writeBits(3, 2); + expect(buffer.bytePtr).equals(0); + expect(buffer.bitPtr).equals(5); + expect(buffer.data[0]).equals(192); + + buffer.setPackingDirection(false /** least to most significant */); + expect(buffer.bytePtr).equals(1); + expect(buffer.bitPtr).equals(0); + + buffer.writeBits(7, 3); + expect(buffer.data[0]).equals(192); + expect(buffer.data[1]).equals(7); + }); + + it('throws when switching packing direction and no more bytes left', () => { + buffer.writeBits(0, 25); + expect(() => buffer.setPackingDirection(false)).throws(); + }); }); }); diff --git a/tests/io-bitstream.spec.js b/tests/io-bitstream.spec.js index d4f863d..31cbd7f 100644 --- a/tests/io-bitstream.spec.js +++ b/tests/io-bitstream.spec.js @@ -19,10 +19,22 @@ describe('bitjs.io.BitStream', () => { } }); - it('BitPeekAndRead_RTL', () => { + it('throws an error without an ArrayBuffer', () => { + expect(() => new BitStream()).throws(); + }); + + it('BitPeekAndRead_MTL', () => { const stream = new BitStream(array.buffer, true /* mtl */); + + expect(stream.peekBits(0)).equals(0); + expect(stream.peekBits(-1)).equals(0); + expect(stream.bytePtr).equals(0); + expect(stream.bitPtr).equals(0); + // 0110 = 2 + 4 = 6 expect(stream.readBits(4)).equals(6); + expect(stream.getNumBitsRead()).equals(4); + // 0101 011 = 1 + 2 + 8 + 32 = 43 expect(stream.readBits(7)).equals(43); // 00101 01100101 01 = 1 + 4 + 16 + 128 + 256 + 1024 + 4096 = 5525 @@ -32,11 +44,19 @@ describe('bitjs.io.BitStream', () => { // Ensure the last bit is read, even if we flow past the end of the stream. expect(stream.readBits(2)).equals(1); + + expect(stream.getNumBitsRead()).equals(33); }); - it('BitPeekAndRead_LTR', () => { + it('BitPeekAndRead_LTM', () => { + /** @type {BitStream} */ const stream = new BitStream(array.buffer, false /* mtl */); + expect(stream.peekBits(0)).equals(0); + expect(stream.peekBits(-1)).equals(0); + expect(stream.bytePtr).equals(0); + expect(stream.bitPtr).equals(0); + // 0101 = 2 + 4 = 6 expect(stream.peekBits(4)).equals(5); expect(stream.readBits(4)).equals(5); @@ -69,4 +89,10 @@ describe('bitjs.io.BitStream', () => { expect(() => stream.readBytes(3)).throws(); }); + + it('throws an error with weird values of peekBytes()', () => { + /** @type {BitStream} */ + const stream = new BitStream(array.buffer); + expect(() => stream.peekBytes(-1)).throws(); + }); }); diff --git a/tests/io-bytebuffer.spec.js b/tests/io-bytebuffer.spec.js index 54355d9..a954df8 100644 --- a/tests/io-bytebuffer.spec.js +++ b/tests/io-bytebuffer.spec.js @@ -7,31 +7,41 @@ */ import { ByteBuffer } from '../io/bytebuffer.js'; -import { ByteStream } from '../io/bytestream.js'; import 'mocha'; import { expect } from 'chai'; -// TODO: Only test ByteBuffer here. describe('bitjs.io.ByteBuffer', () => { + /** @type {ByteBuffer} */ let buffer; beforeEach(() => { buffer = new ByteBuffer(4); }); - it('Write_SingleByte', () => { - buffer.writeNumber(192, 1); - expect(buffer.ptr).equals(1); + it('throws when initialized incorrectly', () => { + expect(() => new ByteBuffer()).throws(); }); - it('Write_SingleByteNegativeNumber', () => { + it('insertByte()', () => { + buffer.insertByte(192); + expect(buffer.ptr).equals(1); + expect(buffer.data[0]).equals(192); + }); + + it('writeNumber() with a single unsigned byte', () => { + buffer.writeNumber(192, 1); + expect(buffer.ptr).equals(1); + expect(buffer.data[0]).equals(192); + }); + + it('writeNumber() with a single negative number', () => { buffer.writeSignedNumber(-120, 1); expect(buffer.ptr).equals(1); + expect(buffer.data[0]).equals(-120 & 0xff); }); it('Write_MultiByteNumber', () => { buffer.writeNumber(1234, 4); - const stream = new ByteStream(buffer.data.buffer); expect(buffer.ptr).equals(4); }); @@ -51,4 +61,21 @@ describe('bitjs.io.ByteBuffer', () => { it('WriteOverflowSignedNegative', () => { expect(() => buffer.writeSignedNumber(-129, 1)).throws(); }); + + it('throws when trying to write invalid # of bytes', () => { + expect(() => buffer.writeNumber(3, -1)).throws(); + expect(() => buffer.writeNumber(-3, 1)).throws(); + expect(() => buffer.writeSignedNumber(-3, -1)).throws(); + }); + + it('writes an ASCII string', () => { + buffer.writeASCIIString('hi'); + expect(buffer.ptr).equals(2); + expect(buffer.data[0]).equals('h'.charCodeAt(0)); + expect(buffer.data[1]).equals('i'.charCodeAt(0)); + }); + + it('throws in a non-ASCII string', () => { + expect(() => buffer.writeASCIIString('Björk')).throws('Trying to write a non-ASCII string'); + }); }); \ No newline at end of file diff --git a/tests/io-bytestream.spec.js b/tests/io-bytestream.spec.js index 7d70af6..b3ea402 100644 --- a/tests/io-bytestream.spec.js +++ b/tests/io-bytestream.spec.js @@ -17,6 +17,35 @@ describe('bitjs.io.ByteStream', () => { array = new Uint8Array(4); }); + it('throws an error without an ArrayBuffer', () => { + expect(() => new ByteStream()).throws(); + expect(() => new ByteStream(array.buffer).push()).throws(); + }); + + it('getNumBytesRead() works', () => { + const stream = new ByteStream(array.buffer); + expect(stream.getNumBytesRead()).equals(0); + stream.readBytes(1); + expect(stream.getNumBytesRead()).equals(1); + stream.readBytes(2); + expect(stream.getNumBytesRead()).equals(3); + }); + + it('throws when peeking a weird numbers of bytes', () => { + array[0] = 255; + const stream = new ByteStream(array.buffer); + expect(stream.peekNumber(0)).equals(0); + expect(() => stream.peekNumber(-2)).throws(); + expect(() => stream.peekNumber(5)).throws(); + + expect(stream.peekBytes(0).length).equals(0); + expect(() => stream.peekBytes(-1)).throws(); + + expect(stream.peekString(0)).equals(''); + expect(() => stream.peekString(-1)).throws(); + expect(() => stream.peekString(5)).throws(); + }); + it('PeekAndRead_SingleByte', () => { array[0] = 192; const stream = new ByteStream(array.buffer);