diff --git a/.gitignore b/.gitignore index fdd41e0..163f79a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ package-lock.json .idea/ node_modules/ +coverage/ diff --git a/package.json b/package.json index 89439b7..3597ddf 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "1.3.1-r1", "description": "A Node.js module for interfacing with Repertory's remote mount API", "scripts": { - "test": "jest" + "test": "jest", + "coverage": "jest --collect-coverage" }, "keywords": [ "repertory", diff --git a/src/__tests__/connection_pool.test.js b/src/__tests__/connection_pool.test.js new file mode 100644 index 0000000..01b1dbd --- /dev/null +++ b/src/__tests__/connection_pool.test.js @@ -0,0 +1,43 @@ +import connection_pool from '../networking/connection_pool'; +import packet from '../networking/packet'; +import connection from '../networking/connection'; + +jest.mock('../networking/connection'); + +test(`construction fails if pool size is <= 1`, () => { + expect(() => new connection_pool(1)).toThrow(Error); + expect(() => new connection_pool(0)).toThrow(Error); + expect(() => new connection_pool(-1)).toThrow(Error); +}); + +test(`error on socket release is ignored`, async () => { + + const conn = new connection_pool(2, '', 20000); + let invoked = false; + jest.spyOn(conn.pool, 'acquire').mockImplementation(() => { + return { + release: () => { + invoked = true; + throw new Error('mock release error'); + }, + } + }); + + const mock_send = jest.fn(); + connection.prototype.send = async () => { + return mock_send(); + }; + mock_send.mockResolvedValue(0); + + expect(await conn.send('', new packet())).toEqual(0); + expect(invoked).toBeTruthy(); +}); + +test(`send fails if acquire fails`, async () => { + const conn = new connection_pool(2, '', 20000); + jest.spyOn(conn.pool, 'acquire').mockImplementation(() => { + throw new Error('mock acquire exception'); + }); + + await expect(conn.send('', new packet())).rejects.toThrow(Error); +}); diff --git a/src/__tests__/file.test.js b/src/__tests__/file.test.js new file mode 100644 index 0000000..6e1ab4f --- /dev/null +++ b/src/__tests__/file.test.js @@ -0,0 +1,49 @@ +import file from '../io/file'; + +jest.mock('../ops/index.js', () => ( + { + ...(jest.requireActual('../ops/index.js')), + close_file: jest.fn(), + } +)); + +import {close_file} from '../ops/index'; + +test(`can close a closed file`, async () => { + const f = new file(); + expect(await f.close()).toEqual(0); +}); + +test(`'get_size' fails on closed file`, async () => { + const f = new file(); + await expect(f.get_size()).rejects.toThrow(Error); +}); + +test(`'read' fails on closed file`, async () => { + const f = new file(); + await expect(f.read(0, 10)).rejects.toThrow(Error); +}); + +test(`'truncate' fails on closed file`, async () => { + const f = new file(); + await expect(f.truncate(0)).rejects.toThrow(Error); +}); + +test(`'write' fails on closed file`, async () => { + const f = new file(); + await expect(f.write(0, Buffer.alloc(2))).rejects.toThrow(Error); +}); + +test(`handle is set to null on close`, async () => { + const f = new file(null, 1, '/path'); + close_file.mockReturnValue(0); + expect(await f.close()).toEqual(0); + expect(f.handle).toBeNull(); +}); + +test(`handle is not changed on close if return is not 0`, async () => { + const f = new file(null, 1, '/path'); + close_file.mockReturnValue(1); + expect(await f.close()).toEqual(1); + expect(f.handle).toBe(1); +}); diff --git a/src/io/file.js b/src/io/file.js index 11773a2..091cbbc 100644 --- a/src/io/file.js +++ b/src/io/file.js @@ -5,7 +5,7 @@ let next_thread_id = 1; export default class file { constructor(conn, handle, remote_path) { this.conn = conn; - this.handle = handle; + this.handle = handle || null; this.remote_path = remote_path; this.thread_id = next_thread_id++; }