Skip to content

Commit

Permalink
[wip] LinkedList cycle fix (#941)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsmkl authored and ashishb committed Sep 17, 2019
1 parent 4fcc603 commit 789d576
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 1 deletion.
4 changes: 4 additions & 0 deletions packages/protocol/contracts/common/linkedlists/LinkedList.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ library LinkedList {
{
require(key != bytes32(0), "Key must be defined");
require(!contains(list, key), "Can't insert an existing element");
require(
previousKey != key && nextKey != key,
"Key cannot be the same as previousKey or nextKey"
);

Element storage element = list.elements[key];
element.exists = true;
Expand Down
48 changes: 48 additions & 0 deletions packages/protocol/contracts/common/test/LinkedListTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
pragma solidity ^0.5.8;

import "../linkedlists/LinkedList.sol";

contract LinkedListTest {
using LinkedList for LinkedList.List;

LinkedList.List private list;

function insert(bytes32 key, bytes32 previousKey, bytes32 nextKey) external {
list.insert(key, previousKey, nextKey);
}

function update(bytes32 key, bytes32 previousKey, bytes32 nextKey) external {
list.update(key, previousKey, nextKey);
}

function remove(bytes32 key) external {
list.remove(key);
}

function contains(bytes32 key) external view returns (bool) {
return list.contains(key);
}

function getNumElements() external view returns (uint256) {
return list.numElements;
}

function getKeys()
external
view
returns (
bytes32[] memory
)
{
return list.getKeys();
}

function head() external view returns (bytes32) {
return list.head;
}

function tail() external view returns (bytes32) {
return list.tail;
}

}
2 changes: 1 addition & 1 deletion packages/protocol/migrationsConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const DefaultConfig = {
}

const linkedLibraries = {
LinkedList: ['AddressLinkedList', 'SortedLinkedList'],
LinkedList: ['AddressLinkedList', 'SortedLinkedList', 'LinkedListTest'],
SortedLinkedList: [
'AddressSortedLinkedList',
'IntegerSortedLinkedList',
Expand Down
86 changes: 86 additions & 0 deletions packages/protocol/test/common/linkedlist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { assertRevert } from '@celo/protocol/lib/test-utils'
// import BigNumber from 'bignumber.js'
import { LinkedListTestContract, LinkedListTestInstance } from 'types'

const LinkedListTest: LinkedListTestContract = artifacts.require('LinkedListTest')

// @ts-ignore
// TODO(mcortesi): Use BN
LinkedListTest.numberFormat = 'BigNumber'

contract('LinkedListTest', () => {
let linkedListTest: LinkedListTestInstance

beforeEach(async () => {
linkedListTest = await LinkedListTest.new()
})

describe('#insert()', () => {
const NULL_KEY = '0x00'
const firstKey = '0x01'
const keys = ['0x01', '0x02', '0x03']
const middleKey = '0x02'
const lastKey = '0x03'
const addedKey = '0x04'

describe('when inserting to empty list', () => {
it('should revert if previous is equal to key', async () => {
await assertRevert(linkedListTest.insert(addedKey, addedKey, NULL_KEY))
})

it('should revert if next is equal to key', async () => {
await assertRevert(linkedListTest.insert(addedKey, NULL_KEY, addedKey))
})
})

describe('when inserting to singleton', () => {
beforeEach(async () => {
await linkedListTest.insert(firstKey, NULL_KEY, NULL_KEY)
})

it('should revert if next is equal to key', async () => {
await assertRevert(linkedListTest.insert(addedKey, firstKey, addedKey))
})

it('should revert if previous is equal to key', async () => {
await assertRevert(linkedListTest.insert(addedKey, addedKey, firstKey))
})
})

describe('when inserting to a list with more items', () => {
beforeEach(async () => {
await linkedListTest.insert(firstKey, NULL_KEY, NULL_KEY)
for (let i = 1; i < keys.length; i++)
await linkedListTest.insert(keys[i], NULL_KEY, keys[i - 1])
})

it('should revert if next is equal to key (beginning)', async () => {
await assertRevert(linkedListTest.insert(addedKey, firstKey, addedKey))
})

it('should revert if previous is equal to key (beginning)', async () => {
await assertRevert(linkedListTest.insert(addedKey, addedKey, firstKey))
})

it('should revert if next is equal to key (end)', async () => {
await assertRevert(linkedListTest.insert(addedKey, lastKey, addedKey))
})

it('should revert if previous is equal to key (end)', async () => {
await assertRevert(linkedListTest.insert(addedKey, addedKey, lastKey))
})

it('should revert if next is equal to key (middle)', async () => {
await assertRevert(linkedListTest.insert(addedKey, middleKey, addedKey))
})

it('should revert if previous is equal to key (middle)', async () => {
await assertRevert(linkedListTest.insert(addedKey, addedKey, middleKey))
})

it('should revert if next and previous equal to key', async () => {
await assertRevert(linkedListTest.insert(addedKey, addedKey, addedKey))
})
})
})
})

0 comments on commit 789d576

Please sign in to comment.