import { expect } from 'chai'; import type { SinonStub } from 'sinon'; import { stub } from 'sinon'; import * as process from 'process'; import * as memory from '~/src/memory'; import * as deviceState from '~/src/device-state'; import log from '~/lib/supervisor-console'; describe('memory.healthcheck', () => { let uptimeStub: SinonStub; let rssStub: SinonStub; let isApplyInProgressStub: SinonStub; beforeEach(() => { uptimeStub = stub(memory, 'processUptime').returns(20); rssStub = stub(process.memoryUsage, 'rss').returns(100); isApplyInProgressStub = stub(deviceState, 'isApplyInProgress').returns( false, ); }); afterEach(() => { uptimeStub.restore(); rssStub.restore(); isApplyInProgressStub.restore(); }); it('passes healthcheck if process has not been running for 20s', async () => { // @ts-expect-error - initialMemory is read-only memory.initialMemory = 0; uptimeStub.returns(19); expect(await memory.healthcheck()).to.be.true; }); it('passes healthcheck while initial memory not set and sets initial memory', async () => { // @ts-expect-error - initialMemory is read-only memory.initialMemory = 0; expect(await memory.healthcheck()).to.be.true; expect(memory.initialMemory).to.equal(100); }); it('passes healthcheck while state apply in progress', async () => { // @ts-expect-error - initialMemory is read-only memory.initialMemory = 100; isApplyInProgressStub.returns(true); expect(await memory.healthcheck()).to.be.true; }); it('passes healthcheck if memory usage is below threshold', async () => { // @ts-expect-error - initialMemory is read-only memory.initialMemory = 100; rssStub.returns(150); expect(await memory.healthcheck(100)).to.be.true; }); it('fails healthcheck if memory usage is above threshold', async () => { // @ts-expect-error - initialMemory is read-only memory.initialMemory = 100; uptimeStub.returns(61); rssStub.returns(250); expect(await memory.healthcheck(100)).to.be.false; expect(log.info).to.have.been.calledWith( `Healthcheck failure - memory usage above threshold after 0h 1m 1s`, ); }); });