Skip to content

Commit 5d40e67

Browse files
committed
Add unit tests
1 parent 3a73dcb commit 5d40e67

File tree

1 file changed

+156
-0
lines changed

1 file changed

+156
-0
lines changed

tests/unit/utils/lz4.test.ts

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import { expect } from 'chai';
2+
import sinon from 'sinon';
3+
4+
describe('lz4 module loader', () => {
5+
let moduleLoadStub: sinon.SinonStub | undefined;
6+
let consoleWarnStub: sinon.SinonStub;
7+
8+
beforeEach(() => {
9+
consoleWarnStub = sinon.stub(console, 'warn');
10+
});
11+
12+
afterEach(() => {
13+
consoleWarnStub.restore();
14+
if (moduleLoadStub) {
15+
moduleLoadStub.restore();
16+
}
17+
// Clear module cache
18+
Object.keys(require.cache).forEach((key) => {
19+
if (key.includes('lz4')) {
20+
delete require.cache[key];
21+
}
22+
});
23+
});
24+
25+
const mockModuleLoad = (lz4MockOrError: unknown): { restore: () => void; wasLz4LoadAttempted: () => boolean } => {
26+
// eslint-disable-next-line global-require
27+
const Module = require('module');
28+
const originalLoad = Module._load;
29+
let lz4LoadAttempted = false;
30+
31+
Module._load = (request: string, parent: unknown, isMain: boolean) => {
32+
if (request === 'lz4') {
33+
lz4LoadAttempted = true;
34+
if (lz4MockOrError instanceof Error) {
35+
throw lz4MockOrError;
36+
}
37+
return lz4MockOrError;
38+
}
39+
return originalLoad.call(Module, request, parent, isMain);
40+
};
41+
42+
return {
43+
restore: () => {
44+
Module._load = originalLoad;
45+
},
46+
wasLz4LoadAttempted: () => lz4LoadAttempted,
47+
};
48+
};
49+
50+
const loadLz4Module = () => {
51+
delete require.cache[require.resolve('../../../lib/utils/lz4')];
52+
// eslint-disable-next-line global-require
53+
return require('../../../lib/utils/lz4');
54+
};
55+
56+
it('should successfully load and use lz4 module when available', () => {
57+
const fakeLz4 = {
58+
encode: (buf: Buffer) => {
59+
const compressed = Buffer.from(`compressed:${buf.toString()}`);
60+
return compressed;
61+
},
62+
decode: (buf: Buffer) => {
63+
const decompressed = buf.toString().replace('compressed:', '');
64+
return Buffer.from(decompressed);
65+
},
66+
};
67+
68+
const { restore } = mockModuleLoad(fakeLz4);
69+
const moduleExports = loadLz4Module();
70+
const lz4Module = moduleExports.default();
71+
restore();
72+
73+
expect(lz4Module).to.not.be.undefined;
74+
expect(lz4Module.encode).to.be.a('function');
75+
expect(lz4Module.decode).to.be.a('function');
76+
77+
const testData = Buffer.from('Hello, World!');
78+
const compressed = lz4Module.encode(testData);
79+
const decompressed = lz4Module.decode(compressed);
80+
81+
expect(decompressed.toString()).to.equal('Hello, World!');
82+
expect(consoleWarnStub.called).to.be.false;
83+
});
84+
85+
it('should return undefined when lz4 module fails to load with MODULE_NOT_FOUND', () => {
86+
const err: NodeJS.ErrnoException = new Error("Cannot find module 'lz4'");
87+
err.code = 'MODULE_NOT_FOUND';
88+
89+
const { restore } = mockModuleLoad(err);
90+
const moduleExports = loadLz4Module();
91+
const lz4Module = moduleExports.default();
92+
restore();
93+
94+
expect(lz4Module).to.be.undefined;
95+
expect(consoleWarnStub.called).to.be.false;
96+
});
97+
98+
it('should return undefined and log warning when lz4 fails with ERR_DLOPEN_FAILED', () => {
99+
const err: NodeJS.ErrnoException = new Error('Module did not self-register');
100+
err.code = 'ERR_DLOPEN_FAILED';
101+
102+
const { restore } = mockModuleLoad(err);
103+
const moduleExports = loadLz4Module();
104+
const lz4Module = moduleExports.default();
105+
restore();
106+
107+
expect(lz4Module).to.be.undefined;
108+
expect(consoleWarnStub.calledOnce).to.be.true;
109+
expect(consoleWarnStub.firstCall.args[0]).to.include('Architecture or version mismatch');
110+
});
111+
112+
it('should return undefined and log warning when lz4 fails with unknown error code', () => {
113+
const err: NodeJS.ErrnoException = new Error('Some unknown error');
114+
err.code = 'UNKNOWN_ERROR';
115+
116+
const { restore } = mockModuleLoad(err);
117+
const moduleExports = loadLz4Module();
118+
const lz4Module = moduleExports.default();
119+
restore();
120+
121+
expect(lz4Module).to.be.undefined;
122+
expect(consoleWarnStub.calledOnce).to.be.true;
123+
expect(consoleWarnStub.firstCall.args[0]).to.include('Unhandled error code');
124+
});
125+
126+
it('should return undefined and log warning when error has no code property', () => {
127+
const err = new Error('Error without code');
128+
129+
const { restore } = mockModuleLoad(err);
130+
const moduleExports = loadLz4Module();
131+
const lz4Module = moduleExports.default();
132+
restore();
133+
134+
expect(lz4Module).to.be.undefined;
135+
expect(consoleWarnStub.calledOnce).to.be.true;
136+
expect(consoleWarnStub.firstCall.args[0]).to.include('Invalid error object');
137+
});
138+
139+
it('should not attempt to load lz4 module when getResolvedModule is not called', () => {
140+
const fakeLz4 = {
141+
encode: () => Buffer.from(''),
142+
decode: () => Buffer.from(''),
143+
};
144+
145+
const { restore, wasLz4LoadAttempted } = mockModuleLoad(fakeLz4);
146+
147+
// Load the module but don't call getResolvedModule
148+
loadLz4Module();
149+
// Note: we're NOT calling .default() here
150+
151+
restore();
152+
153+
expect(wasLz4LoadAttempted()).to.be.false;
154+
expect(consoleWarnStub.called).to.be.false;
155+
});
156+
});

0 commit comments

Comments
 (0)