Skip to content

Commit

Permalink
test: increase coverage (100% functions)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenctw committed Oct 2, 2023
1 parent b1af00d commit a05c759
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 63 deletions.
74 changes: 74 additions & 0 deletions permissionless-arbitration/contracts/test/Clock.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2023 Cartesi Pte. Ltd.

// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

import "forge-std/Test.sol";

import "src/Clock.sol";

pragma solidity ^0.8.0;

contract ClockTest is Test {
using Clock for Clock.State;
using Time for Time.Instant;

Clock.State clock1;
Clock.State clock2;

uint64 constant clock1Allowance = 20;
uint64 constant clock2Allowance = 30;

function setUp() public {
Clock.setNewPaused(
clock1, Time.currentTime(), Time.Duration.wrap(clock1Allowance)
);
Clock.setNewPaused(
clock2, Time.currentTime(), Time.Duration.wrap(clock2Allowance)
);
}

function testMax() public {
Time.Duration max = clock1.max(clock2);
assertEq(
Time.Duration.unwrap(max),
30,
"should return max of two paused clocks"
);
}

function testAdvanceClock() public {
assertTrue(clock1.startInstant.isZero(), "clock1 should be set paused");

clock1.advanceClock();
assertTrue(
!clock1.startInstant.isZero(), "clock1 should be set running"
);

clock1.advanceClock();
assertTrue(clock1.startInstant.isZero(), "clock1 should be set paused");
}

function testTimeLeft() public {
assertTrue(clock1.hasTimeLeft(), "clock1 should have time left");

clock1.advanceClock();
assertTrue(clock1.hasTimeLeft(), "clock1 should have time left");

vm.warp(block.timestamp + clock1Allowance - 1);
assertTrue(clock1.hasTimeLeft(), "clock1 should have time left");

vm.warp(block.timestamp + clock1Allowance);
assertTrue(!clock1.hasTimeLeft(), "clock1 should run out of time");

vm.expectRevert("can't advance clock with no time left");
clock1.advanceClock();
}
}
1 change: 1 addition & 0 deletions permissionless-arbitration/contracts/test/Match.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pragma solidity ^0.8.0;
// TODO: we cannot set the height of a match anymore
// To properly test, we'll need to swap the implementation of
// ArbitrationConstants.
// Or wait until `mockCall` works on internal calls `https://github.com/foundry-rs/foundry/issues/432`

/*
contract MatchTest is Test {
Expand Down
140 changes: 127 additions & 13 deletions permissionless-arbitration/contracts/test/MultiTournament.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

import "forge-std/console.sol";
import "forge-std/Test.sol";

import "./Util.sol";
Expand All @@ -23,11 +22,13 @@ contract MultiTournamentTest is Util, Test {
using Tree for Tree.Node;
using Time for Time.Instant;
using Match for Match.Id;
using Match for Match.State;
using Machine for Machine.Hash;

TournamentFactory immutable factory;
TopTournament topTournament;
MiddleTournament middleTournament;
BottomTournament bottomTournament;

event matchCreated(
Tree.Node indexed one, Tree.Node indexed two, Tree.Node leftOfTwo
Expand Down Expand Up @@ -56,7 +57,7 @@ contract MultiTournamentTest is Util, Test {
// player 0 should win after fast forward time to tournament finishes
uint256 _t = block.timestamp;
uint256 _tournamentFinish =
_t + 1 + Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE);
_t + Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE);

vm.warp(_tournamentFinish);
(_finished, _winner, _finalState) = topTournament.arbitrationResult();
Expand All @@ -77,7 +78,7 @@ contract MultiTournamentTest is Util, Test {
// rewind time in half and pair commitment, expect a match
vm.warp(_t);
// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);

// no dangling commitment available, should revert
vm.warp(_tournamentFinish);
Expand All @@ -91,14 +92,107 @@ contract MultiTournamentTest is Util, Test {
);
}

function testBottom() public {
topTournament = Util.initializePlayer0Tournament(factory);

// pair commitment, expect a match
// player 1 joins tournament
Util.joinTournament(topTournament, 1, 0);

Match.Id memory _matchId = Util.matchId(1, 0);
Match.State memory _match =
topTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to left tree
uint256 _playerToSeal =
Util.advanceMatch01AtLevel(topTournament, _matchId, 0);

// expect new inner created
vm.recordLogs();

// seal match
Util.sealInnerMatchAndCreateInnerTournament(
topTournament, _matchId, _playerToSeal
);

Vm.Log[] memory _entries = vm.getRecordedLogs();
assertEq(_entries[0].topics.length, 2);
assertEq(
_entries[0].topics[0],
keccak256("newInnerTournament(bytes32,address)")
);
assertEq(
_entries[0].topics[1], Match.IdHash.unwrap(_matchId.hashFromId())
);

middleTournament = MiddleTournament(
address(bytes20(bytes32(_entries[0].data) << (12 * 8)))
);

Util.joinTournament(middleTournament, 0, 1);
Util.joinTournament(middleTournament, 1, 1);

_matchId = Util.matchId(1, 1);
_match = middleTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to left tree
_playerToSeal =
Util.advanceMatch01AtLevel(middleTournament, _matchId, 1);

// expect new inner created (bottom)
vm.recordLogs();

// seal match
Util.sealInnerMatchAndCreateInnerTournament(
middleTournament, _matchId, _playerToSeal
);

_entries = vm.getRecordedLogs();
assertEq(_entries[0].topics.length, 2);
assertEq(
_entries[0].topics[0],
keccak256("newInnerTournament(bytes32,address)")
);
assertEq(
_entries[0].topics[1], Match.IdHash.unwrap(_matchId.hashFromId())
);

bottomTournament = BottomTournament(
address(bytes20(bytes32(_entries[0].data) << (12 * 8)))
);

Util.joinTournament(bottomTournament, 0, 2);
Util.joinTournament(bottomTournament, 1, 2);

_matchId = Util.matchId(1, 2);
_match = bottomTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to left tree
_playerToSeal =
Util.advanceMatch01AtLevel(bottomTournament, _matchId, 2);

// seal match
Util.sealLeafMatch(bottomTournament, _matchId, _playerToSeal);

vm.expectRevert();
// win match, expect revert
Util.winLeafMatch(bottomTournament, _matchId, _playerToSeal);
}

function testInner() public {
topTournament = Util.initializePlayer0Tournament(factory);

// pair commitment, expect a match
// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);

Match.Id memory _matchId = Util.matchId(1, 0);
Match.State memory _match =
topTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to left tree
uint256 _playerToSeal =
Expand All @@ -113,9 +207,11 @@ contract MultiTournamentTest is Util, Test {

// pair commitment, expect a match
// player 2 joins tournament
Util.joinTopTournament(topTournament, 2);
Util.joinTournament(topTournament, 2, 0);

_matchId = Util.matchId(2, 0);
_match = topTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to right tree
_playerToSeal = Util.advanceMatch02AtLevel(topTournament, _matchId, 0);
Expand All @@ -131,9 +227,12 @@ contract MultiTournamentTest is Util, Test {

// pair commitment, expect a match
// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);

Match.Id memory _matchId = Util.matchId(1, 0);
Match.State memory _match =
topTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to left tree
uint256 _playerToSeal =
Expand Down Expand Up @@ -168,10 +267,10 @@ contract MultiTournamentTest is Util, Test {
// player 0 should win after fast forward time to inner tournament finishes
uint256 _t = block.timestamp;
// the delay is increased when a match is created
uint256 _rootTournamentFinish = _t + 1
uint256 _rootTournamentFinish = _t
+ Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE)
+ Time.Duration.unwrap(ArbitrationConstants.MATCH_EFFORT);
Util.joinMiddleTournament(middleTournament, 0, 1);
Util.joinTournament(middleTournament, 0, 1);

vm.warp(_rootTournamentFinish);
(_finished, _winner,) = middleTournament.innerTournamentWinner();
Expand Down Expand Up @@ -204,9 +303,11 @@ contract MultiTournamentTest is Util, Test {

// pair commitment, expect a match
// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);

_matchId = Util.matchId(1, 0);
_match = topTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

// advance match to end, this match will always advance to left tree
_playerToSeal = Util.advanceMatch01AtLevel(topTournament, _matchId, 0);
Expand Down Expand Up @@ -239,30 +340,43 @@ contract MultiTournamentTest is Util, Test {
_t = block.timestamp;
// the delay is increased when a match is created
_rootTournamentFinish =
_t + 1 + Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE);
_t + Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE);
uint256 _middleTournamentFinish = _rootTournamentFinish
+ Time.Duration.unwrap(ArbitrationConstants.MATCH_EFFORT);

Util.joinMiddleTournament(middleTournament, 0, 1);
Util.joinTournament(middleTournament, 0, 1);

//let player 1 join, then timeout player 0
Util.joinMiddleTournament(middleTournament, 1, 1);
Util.joinTournament(middleTournament, 1, 1);

(Clock.State memory _player0Clock,) = middleTournament.getCommitment(
playerNodes[0][ArbitrationConstants.height(1)]
);
_matchId = Util.matchId(1, 1);
_match = middleTournament.getMatch(_matchId.hashFromId());
assertTrue(_match.exists(), "match should exist");

vm.expectRevert("cannot win by timeout");
middleTournament.winMatchByTimeout(
_matchId,
playerNodes[1][ArbitrationConstants.height(1) - 1],
playerNodes[1][ArbitrationConstants.height(1) - 1]
);

vm.warp(
Time.Instant.unwrap(
_player0Clock.startInstant.add(_player0Clock.allowance)
)
);
_matchId = Util.matchId(1, 1);
middleTournament.winMatchByTimeout(
_matchId,
playerNodes[1][ArbitrationConstants.height(1) - 1],
playerNodes[1][ArbitrationConstants.height(1) - 1]
);

_match = middleTournament.getMatch(_matchId.hashFromId());
assertFalse(_match.exists(), "match should be deleted");

vm.warp(_middleTournamentFinish);
(_finished, _winner,) = middleTournament.innerTournamentWinner();
topTournament.winInnerMatch(
Expand Down
12 changes: 6 additions & 6 deletions permissionless-arbitration/contracts/test/Tournament.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract TournamentTest is Util, Test {

// duplicate commitment should be reverted
vm.expectRevert("clock is initialized");
Util.joinTopTournament(topTournament, 0);
Util.joinTournament(topTournament, 0, 0);

// pair commitment, expect a match
vm.expectEmit(true, true, false, true, address(topTournament));
Expand All @@ -55,20 +55,20 @@ contract TournamentTest is Util, Test {
playerNodes[1][ArbitrationConstants.height(0) - 1]
);
// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);
}

function testTimeout() public {
topTournament = Util.initializePlayer0Tournament(factory);

uint256 _t = block.timestamp;
// the delay is increased when a match is created
uint256 _tournamentFinishWithMatch = _t + 1
uint256 _tournamentFinishWithMatch = _t
+ Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE)
+ Time.Duration.unwrap(ArbitrationConstants.MATCH_EFFORT);

// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);

Match.Id memory _matchId = Util.matchId(1, 0);
assertFalse(
Expand Down Expand Up @@ -117,12 +117,12 @@ contract TournamentTest is Util, Test {
_t = block.timestamp;

// the delay is increased when a match is created
_tournamentFinishWithMatch = _t + 1
_tournamentFinishWithMatch = _t
+ Time.Duration.unwrap(ArbitrationConstants.MAX_ALLOWANCE)
+ Time.Duration.unwrap(ArbitrationConstants.MATCH_EFFORT);

// player 1 joins tournament
Util.joinTopTournament(topTournament, 1);
Util.joinTournament(topTournament, 1, 0);

// player 0 should win after fast forward time to player 1 timeout
// player 1 timeout first because he's supposed to advance match after player 0 advanced
Expand Down
Loading

0 comments on commit a05c759

Please sign in to comment.