Add more tests
- Marketplace tests for requestsForHost, and additional tests for myRequests and mySlots - Added Utils lib with tests - Added additional Bytes32AddressSetMap.keys expectations
This commit is contained in:
parent
429b9034d8
commit
7f59e545b2
|
@ -7,6 +7,7 @@ import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
||||||
import "./Collateral.sol";
|
import "./Collateral.sol";
|
||||||
import "./Proofs.sol";
|
import "./Proofs.sol";
|
||||||
import "./libs/SetMap.sol";
|
import "./libs/SetMap.sol";
|
||||||
|
import "./libs/Utils.sol";
|
||||||
|
|
||||||
contract Marketplace is Collateral, Proofs {
|
contract Marketplace is Collateral, Proofs {
|
||||||
using EnumerableSet for EnumerableSet.Bytes32Set;
|
using EnumerableSet for EnumerableSet.Bytes32Set;
|
||||||
|
@ -43,7 +44,16 @@ contract Marketplace is Collateral, Proofs {
|
||||||
|
|
||||||
function myRequests() public view returns (RequestId[] memory) {
|
function myRequests() public view returns (RequestId[] memory) {
|
||||||
SetMap.AddressBytes32SetMapKey key = _toAddressSetMapKey(msg.sender);
|
SetMap.AddressBytes32SetMapKey key = _toAddressSetMapKey(msg.sender);
|
||||||
return _toRequestIds(activeRequestsForClients.values(key));
|
RequestId[] memory requestIds = _toRequestIds(activeRequestsForClients.values(key));
|
||||||
|
RequestId[] memory result = new RequestId[](requestIds.length);
|
||||||
|
uint8 counter = 0;
|
||||||
|
for (uint8 i = 0; i < requestIds.length; i++) {
|
||||||
|
if (!_isCancelled(requestIds[i])) {
|
||||||
|
result[counter] = requestIds[i];
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _toRequestIds(Utils._resize(_toBytes32s(result), counter));
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestsForHost(address host) public view returns(RequestId[] memory) {
|
function requestsForHost(address host) public view returns(RequestId[] memory) {
|
||||||
|
@ -55,12 +65,14 @@ contract Marketplace is Collateral, Proofs {
|
||||||
for (uint8 i = 0; i < keyLength; i++) {
|
for (uint8 i = 0; i < keyLength; i++) {
|
||||||
RequestId requestId = RequestId.wrap(keys.at(i));
|
RequestId requestId = RequestId.wrap(keys.at(i));
|
||||||
SetMap.Bytes32AddressSetMapKey key = _toBytes32AddressSetMapKey(requestId);
|
SetMap.Bytes32AddressSetMapKey key = _toBytes32AddressSetMapKey(requestId);
|
||||||
if (activeRequestsForHosts.contains(key, host)) {
|
if (activeRequestsForHosts.contains(key, host) &&
|
||||||
|
!_isCancelled(requestId))
|
||||||
|
{
|
||||||
result[counter] = requestId;
|
result[counter] = requestId;
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return _toRequestIds(Utils._resize(_toBytes32s(result), counter));
|
||||||
}
|
}
|
||||||
|
|
||||||
function mySlots(RequestId requestId)
|
function mySlots(RequestId requestId)
|
||||||
|
@ -442,6 +454,17 @@ contract Marketplace is Collateral, Proofs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _toBytes32s(RequestId[] memory array)
|
||||||
|
private
|
||||||
|
pure
|
||||||
|
returns (bytes32[] memory result)
|
||||||
|
{
|
||||||
|
// solhint-disable-next-line no-inline-assembly
|
||||||
|
assembly {
|
||||||
|
result := array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _toSlotId(RequestId requestId, uint256 slotIndex)
|
function _toSlotId(RequestId requestId, uint256 slotIndex)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
|
|
|
@ -315,5 +315,6 @@ library SetMap {
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
map._index[key]++;
|
map._index[key]++;
|
||||||
|
map._keys.remove(Bytes32AddressSetMapKey.unwrap(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.0;
|
||||||
|
|
||||||
|
import "./Utils.sol";
|
||||||
|
|
||||||
|
// exposes public functions for testing
|
||||||
|
contract TestUtils {
|
||||||
|
|
||||||
|
function resize(bytes32[] memory array,
|
||||||
|
uint8 newSize)
|
||||||
|
public
|
||||||
|
pure
|
||||||
|
returns (bytes32[] memory)
|
||||||
|
{
|
||||||
|
return Utils._resize(array, newSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.8;
|
||||||
|
|
||||||
|
library Utils {
|
||||||
|
function _resize(bytes32[] memory array, uint8 newSize)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes32[] memory)
|
||||||
|
{
|
||||||
|
require(newSize <= array.length, "size out of bounds");
|
||||||
|
|
||||||
|
if (newSize == 0) {
|
||||||
|
bytes32[] memory empty;
|
||||||
|
return empty;
|
||||||
|
} else {
|
||||||
|
bytes32[] memory sized = new bytes32[](newSize);
|
||||||
|
for (uint8 i = 0; i < newSize; i++) {
|
||||||
|
sized[i] = array[i];
|
||||||
|
}
|
||||||
|
return sized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -705,6 +705,12 @@ describe("Marketplace", function () {
|
||||||
expect(await marketplace.myRequests()).to.deep.equal([requestId(request)])
|
expect(await marketplace.myRequests()).to.deep.equal([requestId(request)])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("removes request from list when cancelled", async function () {
|
||||||
|
await marketplace.requestStorage(request)
|
||||||
|
await waitUntilCancelled(request)
|
||||||
|
expect(await marketplace.myRequests()).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
it("removes request from list when funds are withdrawn", async function () {
|
it("removes request from list when funds are withdrawn", async function () {
|
||||||
await marketplace.requestStorage(request)
|
await marketplace.requestStorage(request)
|
||||||
await waitUntilCancelled(request)
|
await waitUntilCancelled(request)
|
||||||
|
@ -732,6 +738,56 @@ describe("Marketplace", function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("list of active requests for host", function () {
|
||||||
|
beforeEach(async function () {
|
||||||
|
switchAccount(client)
|
||||||
|
await token.approve(marketplace.address, price(request))
|
||||||
|
await marketplace.requestStorage(request)
|
||||||
|
switchAccount(host)
|
||||||
|
await token.approve(marketplace.address, collateral)
|
||||||
|
await marketplace.deposit(collateral)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("is empty when no slot is filled", async function () {
|
||||||
|
expect(await marketplace.requestsForHost(host.address)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds request to list when filling slot", async function () {
|
||||||
|
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||||
|
expect(await marketplace.requestsForHost(host.address)).to.deep.equal([
|
||||||
|
slot.request,
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("removes request from list when cancelled", async function () {
|
||||||
|
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||||
|
await waitUntilCancelled(request)
|
||||||
|
expect(await marketplace.requestsForHost(host.address)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("removes request from list when funds are withdrawn", async function () {
|
||||||
|
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||||
|
await waitUntilCancelled(request)
|
||||||
|
switchAccount(client)
|
||||||
|
await marketplace.withdrawFunds(slot.request)
|
||||||
|
expect(await marketplace.requestsForHost(host.address)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("removes request from list when request fails", async function () {
|
||||||
|
await waitUntilStarted(marketplace, request, proof)
|
||||||
|
await waitUntilFailed(marketplace, request, slot)
|
||||||
|
expect(await marketplace.requestsForHost(host.address)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("removes request from list when request finishes", async function () {
|
||||||
|
switchAccount(host)
|
||||||
|
await waitUntilStarted(marketplace, request, proof)
|
||||||
|
await waitUntilFinished(marketplace, requestId(request))
|
||||||
|
await marketplace.payoutSlot(slot.request, slot.index)
|
||||||
|
expect(await marketplace.requestsForHost(host.address)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("list of active slots", function () {
|
describe("list of active slots", function () {
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
switchAccount(client)
|
switchAccount(client)
|
||||||
|
@ -762,6 +818,14 @@ describe("Marketplace", function () {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("returns no slots when cancelled", async function () {
|
||||||
|
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||||
|
let slot1 = { ...slot, index: slot.index + 1 }
|
||||||
|
await marketplace.fillSlot(slot.request, slot1.index, proof)
|
||||||
|
await waitUntilCancelled(request)
|
||||||
|
expect(await marketplace.mySlots(slot.request)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
it("removes active slots for all hosts in a request when it fails", async function () {
|
it("removes active slots for all hosts in a request when it fails", async function () {
|
||||||
let halfOfSlots = request.ask.slots / 2
|
let halfOfSlots = request.ask.slots / 2
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,15 @@ describe("SetMap", function () {
|
||||||
hexlify(key),
|
hexlify(key),
|
||||||
hexlify(key1),
|
hexlify(key1),
|
||||||
])
|
])
|
||||||
|
await contract.remove(key1, value)
|
||||||
|
await expect(await contract.keys()).to.deep.equal([
|
||||||
|
hexlify(key),
|
||||||
|
hexlify(key1),
|
||||||
|
])
|
||||||
|
await contract.remove(key1, value1)
|
||||||
|
await expect(await contract.keys()).to.deep.equal([hexlify(key)])
|
||||||
|
await contract.clear(key)
|
||||||
|
await expect(await contract.keys()).to.deep.equal([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("contains a key/value pair", async function () {
|
it("contains a key/value pair", async function () {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
const { ethers } = require("hardhat")
|
||||||
|
const { expect } = require("chai")
|
||||||
|
const { hexlify, randomBytes } = ethers.utils
|
||||||
|
const { exampleAddress } = require("./examples")
|
||||||
|
const { hexZeroPad } = require("ethers/lib/utils")
|
||||||
|
|
||||||
|
describe("Utils", function () {
|
||||||
|
let contract
|
||||||
|
let value1
|
||||||
|
let value2
|
||||||
|
let value3
|
||||||
|
let value4
|
||||||
|
let value5
|
||||||
|
let array
|
||||||
|
|
||||||
|
describe("resize", function () {
|
||||||
|
beforeEach(async function () {
|
||||||
|
let Utils = await ethers.getContractFactory("TestUtils")
|
||||||
|
contract = await Utils.deploy()
|
||||||
|
value1 = hexlify(randomBytes(32))
|
||||||
|
value2 = hexlify(randomBytes(32))
|
||||||
|
value3 = hexlify(randomBytes(32))
|
||||||
|
value4 = hexZeroPad(0, 32)
|
||||||
|
value5 = hexZeroPad(0, 32)
|
||||||
|
array = [value1, value2, value3, value4, value5]
|
||||||
|
})
|
||||||
|
|
||||||
|
it("resizes to zero length if new size is 0", async function () {
|
||||||
|
await expect(await contract.resize(array, 0)).to.deep.equal([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("resizes to specified length", async function () {
|
||||||
|
await expect(await contract.resize(array, 3)).to.deep.equal([
|
||||||
|
value1,
|
||||||
|
value2,
|
||||||
|
value3,
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails to resize to out of bounds length", async function () {
|
||||||
|
await expect(contract.resize(array, 6))
|
||||||
|
.to.be.revertedWith("size out of bounds")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue