Files
Nitro_Render_V3/packages/utils/src/__tests__/NumberBank.test.ts
T
DuckieTM eb4fe80612 🆙 Updates
- Added Test Coverage
- Fix Potential Memory Leaks
2026-01-31 13:21:59 +01:00

186 lines
5.3 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest';
import { NumberBank } from '../NumberBank';
describe('NumberBank', () =>
{
describe('constructor', () =>
{
it('should create bank with specified size', () =>
{
const bank = new NumberBank(5);
// Should be able to reserve 5 numbers (LIFO order - pops from end)
expect(bank.reserveNumber()).toBe(4);
expect(bank.reserveNumber()).toBe(3);
expect(bank.reserveNumber()).toBe(2);
expect(bank.reserveNumber()).toBe(1);
expect(bank.reserveNumber()).toBe(0);
expect(bank.reserveNumber()).toBe(-1); // No more available
});
it('should handle negative size as zero', () =>
{
const bank = new NumberBank(-5);
expect(bank.reserveNumber()).toBe(-1);
});
it('should handle zero size', () =>
{
const bank = new NumberBank(0);
expect(bank.reserveNumber()).toBe(-1);
});
});
describe('reserveNumber', () =>
{
let bank: NumberBank;
beforeEach(() =>
{
bank = new NumberBank(3);
});
it('should return numbers in LIFO order (stack behavior)', () =>
{
// Numbers are added 0, 1, 2 to the array
// pop() returns from the end, so we get 2, 1, 0
expect(bank.reserveNumber()).toBe(2);
expect(bank.reserveNumber()).toBe(1);
expect(bank.reserveNumber()).toBe(0);
});
it('should return -1 when no numbers available', () =>
{
bank.reserveNumber();
bank.reserveNumber();
bank.reserveNumber();
expect(bank.reserveNumber()).toBe(-1);
});
});
describe('freeNumber', () =>
{
let bank: NumberBank;
beforeEach(() =>
{
bank = new NumberBank(3);
});
it('should make number available again after freeing', () =>
{
const num = bank.reserveNumber();
bank.freeNumber(num);
// The freed number should be available again
expect(bank.reserveNumber()).toBe(num);
});
it('should handle freeing in different order', () =>
{
const n1 = bank.reserveNumber();
const n2 = bank.reserveNumber();
const n3 = bank.reserveNumber();
// Free in middle order
bank.freeNumber(n2);
bank.freeNumber(n1);
// Should get them back in LIFO order
expect(bank.reserveNumber()).toBe(n1);
expect(bank.reserveNumber()).toBe(n2);
});
it('should ignore freeing numbers not in reserved list', () =>
{
bank.reserveNumber(); // reserves 2
// Try to free a number that wasn't reserved
bank.freeNumber(999);
// Should still work normally
expect(bank.reserveNumber()).toBe(1);
});
it('should allow reusing freed numbers', () =>
{
// Reserve all
const n1 = bank.reserveNumber();
const n2 = bank.reserveNumber();
const n3 = bank.reserveNumber();
// Free and re-reserve multiple times
bank.freeNumber(n1);
const reused1 = bank.reserveNumber();
expect(reused1).toBe(n1);
bank.freeNumber(n2);
bank.freeNumber(reused1);
expect(bank.reserveNumber()).toBe(reused1);
expect(bank.reserveNumber()).toBe(n2);
});
});
describe('dispose', () =>
{
it('should set internal arrays to null', () =>
{
const bank = new NumberBank(5);
bank.reserveNumber();
bank.dispose();
// After dispose, reserveNumber should fail (arrays are null)
// This will throw an error, which is expected behavior
expect(() => bank.reserveNumber()).toThrow();
});
});
describe('edge cases', () =>
{
it('should handle large bank size', () =>
{
const bank = new NumberBank(1000);
// Reserve all
for (let i = 0; i < 1000; i++)
{
expect(bank.reserveNumber()).toBeGreaterThanOrEqual(0);
}
expect(bank.reserveNumber()).toBe(-1);
});
it('should maintain consistency after multiple reserve/free cycles', () =>
{
const bank = new NumberBank(10);
const reserved: number[] = [];
// Reserve 5
for (let i = 0; i < 5; i++)
{
reserved.push(bank.reserveNumber());
}
// Free 3
bank.freeNumber(reserved[0]);
bank.freeNumber(reserved[2]);
bank.freeNumber(reserved[4]);
// Reserve 3 more (should get the freed ones)
const newReserved: number[] = [];
for (let i = 0; i < 3; i++)
{
newReserved.push(bank.reserveNumber());
}
// All previously freed numbers should be reserved again
expect(newReserved).toContain(reserved[0]);
expect(newReserved).toContain(reserved[2]);
expect(newReserved).toContain(reserved[4]);
});
});
});