Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Arrays library with unit tests (#1209) #1375

Merged
merged 3 commits into from
Oct 8, 2018

Conversation

jbogacz
Copy link
Contributor

@jbogacz jbogacz commented Oct 3, 2018

  • prepared due to snapshot token requirements
  • add library with method to find upper bound
  • add unit test for basic and edge cases

Blocks PR #1331

🚀 Description

Arrays library which is the requirement for ERC20 token with snapshots. Blocks PR #1331.

  • [+] 📘 I've reviewed the OpenZeppelin Contributor Guidelines
  • [+] ✅ I've added tests where applicable to test my new functionality.
  • [+] 📖 I've made sure that my contracts are well-documented.
  • [+] 🎨 I've run the JS/Solidity linters and fixed any issues (npm run lint:fix).

@jbogacz
Copy link
Contributor Author

jbogacz commented Oct 3, 2018

@frangio @nventuro hey guys! I'm not sure if does it stick to general concept but I tried. Let me know if you have any comments or ideas for missing test cases.

    * prepared due to snapshot token requirements
    * add library with method to find upper bound
    * add unit test for basic and edge cases
@jbogacz jbogacz force-pushed the fix/Add-Arrays-library-#1209 branch from c420dd1 to 0e8358a Compare October 3, 2018 17:38
Copy link
Contributor

@nventuro nventuro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking care of this @jbogacz! I left a couple comments :) I like how you covered multiple edge cases in your tests!

contracts/utils/Arrays.sol Show resolved Hide resolved
}
}

// At this point at `low` is the exclusive upper bound. We will return the inclusive upper bound.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove 'at'

library Arrays {

/**
* @dev Find upper bound for searching element. Utilize binary search function with O(log(n)) cost.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should improve this documentation: in particular, it is critical to document that element is the value we're searching for, that array is sorted in ascending order, and the return value is an index.

We should also better explain what the function does: given said sorted array, it returns the smallest array index such that the value at that index is larger or equal to the received element, or array.length if no such index exists (i.e. all values inside the array are smaller that the target). It also returns 0 for an empty array, though we may want to revert in that scenario.

});

function range (start, end) {
return Array(end - start + 1).fill().map((_, idx) => start + idx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation might not match people's expectations, since lodash's range doesn't include end. Could we also add a short comment describing what it does?

(await this.arrays.findUpperBound(139)).should.be.bignumber.equal(11);
});

it('should return `index 0` for the first element', async function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd change these to just 'should return 0 for the first element'

});

it('should return `last index + 1` for the element over the upper boundary', async function () {
(await this.arrays.findUpperBound(512)).should.be.bignumber.equal(129);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that the array is 129 elements long, and the first element is 128, may be a bit confusing. Consider using e.g. a shorter array.

this.arrays = await ArraysImpl.new(WITH_GAP_ARRAY);
});

it('should return `last index + 1` of first range for the element from the gap', async function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like what you're testing for here, but fear it may be hard to follow, due to the arrays being generated by range, and there being so many magic numbers. What if we simply made a short test array? e.g. const gapArray = [0, 1, 2, 3,4, 8, 9, 10, 11], and then test for 7.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may also want to use a shorter range in all tests, actually, to make it easier for the reader to understand what's going on.

.should();

contract('Arrays', function () {
context('Odd number of elements', function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the testing for odd and even elements! We should also add a test for an empty array (and decide what to do in that scenario).

Simplify Arrays.test.js to use short arrays as test date
@nventuro nventuro added feature New contracts, functions, or helpers. contracts Smart contract code. labels Oct 5, 2018
* Explaned why uint256 mid variable calculated as Math.average is safe to use as index of array.
Copy link
Contributor

@nventuro nventuro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome @jbogacz, thanks for making this happen! Now we can continue work in #1331 😁

@nventuro nventuro merged commit f7e53d9 into OpenZeppelin:master Oct 8, 2018
@jbogacz
Copy link
Contributor Author

jbogacz commented Oct 8, 2018

Nice, just want to thanks again for your help here 😄 I will go for #1331 now.

@jbogacz jbogacz deleted the fix/Add-Arrays-library-#1209 branch October 8, 2018 14:08
nventuro pushed a commit to nventuro/openzeppelin-contracts that referenced this pull request Oct 18, 2018
…1375)

*     Add Arrays library with unit tests (OpenZeppelin#1209)

    * prepared due to snapshot token requirements
    * add library with method to find upper bound
    * add unit test for basic and edge cases

* Imporove documentation for Arrays library

Simplify Arrays.test.js to use short arrays as test date

* Added comment for uint256 mid variable.
* Explaned why uint256 mid variable calculated as Math.average is safe to use as index of array.

(cherry picked from commit f7e53d9)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contracts Smart contract code. feature New contracts, functions, or helpers.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants