CircularBuffer.test.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. const { ethers } = require('hardhat');
  2. const { expect } = require('chai');
  3. const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
  4. const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
  5. const { generators } = require('../../helpers/random');
  6. const LENGTH = 4;
  7. async function fixture() {
  8. const mock = await ethers.deployContract('$CircularBuffer');
  9. await mock.$setup(0, LENGTH);
  10. return { mock };
  11. }
  12. describe('CircularBuffer', function () {
  13. beforeEach(async function () {
  14. Object.assign(this, await loadFixture(fixture));
  15. });
  16. it('reverts on invalid setup', async function () {
  17. await expect(this.mock.$setup(0, 0)).to.be.revertedWithCustomError(this.mock, 'InvalidBufferSize');
  18. });
  19. it('starts empty', async function () {
  20. expect(await this.mock.$count(0)).to.equal(0n);
  21. expect(await this.mock.$length(0)).to.equal(LENGTH);
  22. expect(await this.mock.$includes(0, ethers.ZeroHash)).to.be.false;
  23. await expect(this.mock.$last(0, 0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
  24. });
  25. it('push', async function () {
  26. const values = Array.from({ length: LENGTH + 3 }, generators.bytes32);
  27. for (const [i, value] of values.map((v, i) => [i, v])) {
  28. // push value
  29. await this.mock.$push(0, value);
  30. // view of the values
  31. const pushed = values.slice(0, i + 1);
  32. const stored = pushed.slice(-LENGTH);
  33. const dropped = pushed.slice(0, -LENGTH);
  34. // check count
  35. expect(await this.mock.$length(0)).to.equal(LENGTH);
  36. expect(await this.mock.$count(0)).to.equal(stored.length);
  37. // check last
  38. for (const j in stored) {
  39. expect(await this.mock.$last(0, j)).to.equal(stored.at(-j - 1));
  40. }
  41. await expect(this.mock.$last(0, stored.length + 1)).to.be.revertedWithPanic(
  42. PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS,
  43. );
  44. // check included and non-included values
  45. for (const v of stored) {
  46. expect(await this.mock.$includes(0, v)).to.be.true;
  47. }
  48. for (const v of dropped) {
  49. expect(await this.mock.$includes(0, v)).to.be.false;
  50. }
  51. expect(await this.mock.$includes(0, ethers.ZeroHash)).to.be.false;
  52. }
  53. });
  54. it('clear', async function () {
  55. const value = generators.bytes32();
  56. await this.mock.$push(0, value);
  57. expect(await this.mock.$count(0)).to.equal(1n);
  58. expect(await this.mock.$length(0)).to.equal(LENGTH);
  59. expect(await this.mock.$includes(0, value)).to.be.true;
  60. await this.mock.$last(0, 0); // not revert
  61. await this.mock.$clear(0);
  62. expect(await this.mock.$count(0)).to.equal(0n);
  63. expect(await this.mock.$length(0)).to.equal(LENGTH);
  64. expect(await this.mock.$includes(0, value)).to.be.false;
  65. await expect(this.mock.$last(0, 0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
  66. });
  67. });