tests: add test coverage for the queue contract (#33)
* tests: add 100% test coverage for the queue contract * lint: run prettier on js tests and scripts * feature: allow Queue to efficiently operate on N items * chore: update to use USD in gas reports * chore: enable solidity optimizer with many runsbuddies-main-deployment
parent
9c5980ee09
commit
3e00a306db
@ -1,3 +1,5 @@ |
||||
node_modules/ |
||||
cache/ |
||||
artifacts/ |
||||
artifacts/ |
||||
coverage/ |
||||
coverage.json |
@ -0,0 +1,3 @@ |
||||
module.exports = { |
||||
skipFiles: ["test"], |
||||
}; |
@ -0,0 +1,53 @@ |
||||
// SPDX-License-Identifier: MIT OR Apache-2.0 |
||||
pragma solidity >=0.6.11; |
||||
|
||||
import "../Queue.sol"; |
||||
|
||||
contract TestQueue is QueueManager { |
||||
using QueueLib for QueueLib.Queue; |
||||
|
||||
constructor() QueueManager() {} |
||||
|
||||
// NB: this is unfortunately expensive |
||||
function contains(bytes32 _item) external view returns (bool) { |
||||
return queue.contains(_item); |
||||
} |
||||
|
||||
function lastItem() external view returns (bytes32) { |
||||
return queue.lastItem(); |
||||
} |
||||
|
||||
function peek() external view returns (bytes32 _item) { |
||||
return queue.peek(); |
||||
} |
||||
|
||||
function enqueue(bytes32 _item) external returns (uint256 _last) { |
||||
return queue.enqueue(_item); |
||||
} |
||||
|
||||
function dequeue() external returns (bytes32 _item) { |
||||
return queue.dequeue(); |
||||
} |
||||
|
||||
function enqueueMany(bytes32[] calldata _items) external returns (uint256 _last) { |
||||
return queue.enqueue(_items); |
||||
} |
||||
|
||||
function dequeueMany(uint256 _number) external returns (bytes32[] memory _items) { |
||||
return queue.dequeue(_number); |
||||
} |
||||
|
||||
function length() external view returns (uint256) { |
||||
return queue.length(); |
||||
} |
||||
|
||||
function drain() external { |
||||
while (queue.length() != 0) { |
||||
queue.dequeue(); |
||||
} |
||||
} |
||||
|
||||
function initAgain() external { |
||||
queue.init(); |
||||
} |
||||
} |
@ -1,18 +1,30 @@ |
||||
require("@nomiclabs/hardhat-waffle"); |
||||
require("@nomiclabs/hardhat-ethers"); |
||||
require("hardhat-gas-reporter"); |
||||
require('@nomiclabs/hardhat-waffle'); |
||||
require('hardhat-gas-reporter'); |
||||
require('solidity-coverage'); |
||||
|
||||
require("./scripts"); |
||||
require('./scripts'); |
||||
|
||||
/** |
||||
* @type import('hardhat/config').HardhatUserConfig |
||||
*/ |
||||
module.exports = { |
||||
solidity: "0.7.6", |
||||
solidity: { |
||||
version: '0.7.6', |
||||
settings: { |
||||
optimizer: { |
||||
enabled: true, |
||||
runs: 999999, |
||||
}, |
||||
}, |
||||
}, |
||||
|
||||
gasReporter: { |
||||
currency: 'USD', |
||||
}, |
||||
|
||||
networks: { |
||||
localhost: { |
||||
url: "http://localhost:8545", |
||||
url: 'http://localhost:8545', |
||||
}, |
||||
}, |
||||
}; |
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@ |
||||
const { types } = require("hardhat/config"); |
||||
const { types } = require('hardhat/config'); |
||||
|
||||
task("deploy-home") |
||||
.addParam("slip44", "The origin chain SLIP44 ID", undefined, types.int) |
||||
.addParam("updater", "The origin chain updater", undefined, types.string) |
||||
.addParam("currentRoot", "The current root") |
||||
task('deploy-home') |
||||
.addParam('slip44', 'The origin chain SLIP44 ID', undefined, types.int) |
||||
.addParam('updater', 'The origin chain updater', undefined, types.string) |
||||
.addParam('currentRoot', 'The current root') |
||||
.setAction(async (args) => {}); |
||||
|
@ -1 +1 @@ |
||||
require("./deploy.js"); |
||||
require('./deploy.js'); |
||||
|
@ -0,0 +1,70 @@ |
||||
/* global describe before it */ |
||||
|
||||
const { waffle, ethers } = require('hardhat'); |
||||
const { expect } = require('chai'); |
||||
|
||||
describe('Queue', async () => { |
||||
let queue; |
||||
|
||||
// create a proper hex encoded bytes32 filled with number. e.g 0x01010101...
|
||||
const bytes32 = (num) => `0x${Buffer.alloc(32, num).toString('hex')}`; |
||||
|
||||
before(async () => { |
||||
const Queue = await ethers.getContractFactory('TestQueue'); |
||||
queue = await Queue.deploy(); |
||||
|
||||
await queue.deployed(); |
||||
}); |
||||
|
||||
it('should function as a queue', async () => { |
||||
// we put this here for coverage to check that init properly does nothing
|
||||
queue.initAgain(); |
||||
|
||||
const items = Array.from(new Array(10).keys()).map((i) => bytes32(i)); |
||||
|
||||
for (const [idx, item] of items.entries()) { |
||||
await queue.enqueue(item); |
||||
const length = await queue.length(); |
||||
expect(length).to.equal(idx + 1); |
||||
} |
||||
|
||||
// last item
|
||||
const last = await queue.lastItem(); |
||||
expect(last).to.equal(items[items.length - 1]); |
||||
|
||||
// contains
|
||||
expect(await queue.contains(bytes32(3))).to.be.true; |
||||
expect(await queue.contains(bytes32(0xff))).to.be.false; |
||||
|
||||
for (const [idx, item] of items.entries()) { |
||||
// peek and dequeue
|
||||
const dequeued = await queue.peek(); |
||||
await queue.dequeue(); |
||||
expect(dequeued).to.equal(item); |
||||
|
||||
// length
|
||||
const length = await queue.length(); |
||||
expect(length).to.equal(items.length - idx - 1); |
||||
} |
||||
|
||||
// reverts
|
||||
await expect(queue.dequeue()).to.be.revertedWith('Empty'); |
||||
await expect(queue.peek()).to.be.revertedWith('Empty'); |
||||
|
||||
// Multi-enq
|
||||
await queue.enqueueMany(items); |
||||
let length = await queue.length(); |
||||
expect(length).to.equal(items.length); |
||||
|
||||
// Multi-deq static call to check ret val
|
||||
let deqed = await queue.callStatic.dequeueMany(items.length); |
||||
items.forEach((item, idx) => { |
||||
expect(item).to.equal(deqed[idx]); |
||||
}); |
||||
|
||||
// Multi-deq tx to check function
|
||||
await queue.dequeueMany(items.length); |
||||
length = await queue.length(); |
||||
expect(length).to.equal(0); |
||||
}); |
||||
}); |
Loading…
Reference in new issue