import { addressUtils, chaiSetup, expectContractCallFailedAsync, provider, txDefaults, web3Wrapper, } from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; import * as _ from 'lodash'; import { artifacts, TestLibAddressArrayContract } from '../src'; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('LibAddressArray', () => { let lib: TestLibAddressArrayContract; before(async () => { await blockchainLifecycle.startAsync(); }); after(async () => { await blockchainLifecycle.revertAsync(); }); before(async () => { // Deploy LibAddressArray lib = await TestLibAddressArrayContract.deployFrom0xArtifactAsync( artifacts.TestLibAddressArray, provider, txDefaults, ); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); }); afterEach(async () => { await blockchainLifecycle.revertAsync(); }); describe('append', () => { it('should append to empty array', async () => { const addr = addressUtils.generatePseudoRandomAddress(); const result = await lib.publicAppend.callAsync([], addr); const expected = [addr]; expect(result).to.deep.equal(expected); }); it('should append to non-empty array', async () => { const arr = _.times(3, () => addressUtils.generatePseudoRandomAddress()); const addr = addressUtils.generatePseudoRandomAddress(); const expected = [...arr, addr]; const result = await lib.publicAppend.callAsync(arr, addr); expect(result).to.deep.equal(expected); }); it('should revert if the free memory pointer was moved to before the end of the array', async () => { const arr = _.times(3, () => addressUtils.generatePseudoRandomAddress()); const addr = addressUtils.generatePseudoRandomAddress(); return expectContractCallFailedAsync( lib.testAppendRealloc.callAsync(arr, new BigNumber(-1), addr), RevertReason.InvalidFreeMemoryPtr, ); }); it('should keep the same memory address if free memory pointer does not move', async () => { const arr = _.times(3, () => addressUtils.generatePseudoRandomAddress()); const addr = addressUtils.generatePseudoRandomAddress(); const expected = [...arr, addr]; const [result, oldArrayMemStart, newArrayMemStart] = await lib.testAppendRealloc.callAsync( arr, new BigNumber(0), addr, ); expect(result).to.deep.equal(expected); expect(newArrayMemStart).bignumber.to.be.equal(oldArrayMemStart); }); it('should change memory address if free memory pointer advances', async () => { const arr = _.times(3, () => addressUtils.generatePseudoRandomAddress()); const addr = addressUtils.generatePseudoRandomAddress(); const expected = [...arr, addr]; const [result, oldArrayMemStart, newArrayMemStart] = await lib.testAppendRealloc.callAsync( arr, new BigNumber(1), addr, ); expect(result).to.deep.equal(expected); expect(newArrayMemStart).bignumber.to.not.be.equal(oldArrayMemStart); }); }); describe('contains', () => { it('should return false on an empty array', async () => { const addr = addressUtils.generatePseudoRandomAddress(); const isFound = await lib.publicContains.callAsync([], addr); expect(isFound).to.equal(false); }); it('should return false on a missing item', async () => { const arr = _.times(3, () => addressUtils.generatePseudoRandomAddress()); const addr = addressUtils.generatePseudoRandomAddress(); const isFound = await lib.publicContains.callAsync(arr, addr); expect(isFound).to.equal(false); }); it('should return true on an included item', async () => { const arr = _.times(4, () => addressUtils.generatePseudoRandomAddress()); const addr = _.sample(arr) as string; const isFound = await lib.publicContains.callAsync(arr, addr); expect(isFound).to.equal(true); }); it('should return true on the only item in the array', async () => { const arr = _.times(1, () => addressUtils.generatePseudoRandomAddress()); const isFound = await lib.publicContains.callAsync(arr, arr[0]); expect(isFound).to.equal(true); }); }); describe('indexOf', () => { it('should fail on an empty array', async () => { const addr = addressUtils.generatePseudoRandomAddress(); const [isSuccess] = await lib.publicIndexOf.callAsync([], addr); expect(isSuccess).to.equal(false); }); it('should fail on a missing item', async () => { const arr = _.times(3, () => addressUtils.generatePseudoRandomAddress()); const addr = addressUtils.generatePseudoRandomAddress(); const [isSuccess] = await lib.publicIndexOf.callAsync(arr, addr); expect(isSuccess).to.equal(false); }); it('should succeed on an included item', async () => { const arr = _.times(4, () => addressUtils.generatePseudoRandomAddress()); const expectedIndexOf = _.random(0, arr.length - 1); const addr = arr[expectedIndexOf]; const [isSuccess, index] = await lib.publicIndexOf.callAsync(arr, addr); expect(isSuccess).to.equal(true); expect(index).bignumber.to.equal(expectedIndexOf); }); it('should succeed on the only item in the array', async () => { const arr = _.times(1, () => addressUtils.generatePseudoRandomAddress()); const [isSuccess, index] = await lib.publicIndexOf.callAsync(arr, arr[0]); expect(isSuccess).to.equal(true); expect(index).bignumber.to.equal(0); }); }); }); // tslint:disable:max-file-line-count