Add support for more types in Arrays.sol (#5568)

This commit is contained in:
Hadrien Croubois
2025-03-13 13:44:41 +01:00
committed by GitHub
parent f740084582
commit 8a4eadea51
7 changed files with 208 additions and 72 deletions

View File

@ -119,61 +119,63 @@ describe('Arrays', function () {
}
});
for (const type of TYPES) {
const elements = Array.from({ length: 10 }, generators[type]);
for (const { name, isValueType } of TYPES) {
const elements = Array.from({ length: 10 }, generators[name]);
describe(type, function () {
describe(name, function () {
const fixture = async () => {
return { instance: await ethers.deployContract(`${capitalize(type)}ArraysMock`, [elements]) };
return { instance: await ethers.deployContract(`${capitalize(name)}ArraysMock`, [elements]) };
};
beforeEach(async function () {
Object.assign(this, await loadFixture(fixture));
});
describe('sort', function () {
for (const length of [0, 1, 2, 8, 32, 128]) {
describe(`${type}[] of length ${length}`, function () {
beforeEach(async function () {
this.array = Array.from({ length }, generators[type]);
if (isValueType) {
describe('sort', function () {
for (const length of [0, 1, 2, 8, 32, 128]) {
describe(`${name}[] of length ${length}`, function () {
beforeEach(async function () {
this.array = Array.from({ length }, generators[name]);
});
afterEach(async function () {
const expected = Array.from(this.array).sort(comparator);
const reversed = Array.from(expected).reverse();
expect(await this.instance.sort(this.array)).to.deep.equal(expected);
expect(await this.instance.sortReverse(this.array)).to.deep.equal(reversed);
});
it('sort array', async function () {
// nothing to do here, beforeEach and afterEach already take care of everything.
});
if (length > 1) {
it('sort array for identical elements', async function () {
// duplicate the first value to all elements
this.array.fill(this.array.at(0));
});
it('sort already sorted array', async function () {
// pre-sort the elements
this.array.sort(comparator);
});
it('sort reversed array', async function () {
// pre-sort in reverse order
this.array.sort(comparator).reverse();
});
it('sort almost sorted array', async function () {
// pre-sort + rotate (move the last element to the front) for an almost sorted effect
this.array.sort(comparator);
this.array.unshift(this.array.pop());
});
}
});
afterEach(async function () {
const expected = Array.from(this.array).sort(comparator);
const reversed = Array.from(expected).reverse();
expect(await this.instance.sort(this.array)).to.deep.equal(expected);
expect(await this.instance.sortReverse(this.array)).to.deep.equal(reversed);
});
it('sort array', async function () {
// nothing to do here, beforeEach and afterEach already take care of everything.
});
if (length > 1) {
it('sort array for identical elements', async function () {
// duplicate the first value to all elements
this.array.fill(this.array.at(0));
});
it('sort already sorted array', async function () {
// pre-sort the elements
this.array.sort(comparator);
});
it('sort reversed array', async function () {
// pre-sort in reverse order
this.array.sort(comparator).reverse();
});
it('sort almost sorted array', async function () {
// pre-sort + rotate (move the last element to the front) for an almost sorted effect
this.array.sort(comparator);
this.array.unshift(this.array.pop());
});
}
});
}
});
}
});
}
describe('unsafeAccess', function () {
describe('storage', function () {
@ -197,7 +199,7 @@ describe('Arrays', function () {
});
describe('memory', function () {
const fragment = `$unsafeMemoryAccess(${type}[] arr, uint256 pos)`;
const fragment = `$unsafeMemoryAccess(${name}[] arr, uint256 pos)`;
for (const i in elements) {
it(`unsafeMemoryAccess within bounds #${i}`, async function () {
@ -211,7 +213,9 @@ describe('Arrays', function () {
it('unsafeMemoryAccess loop around', async function () {
for (let i = 251n; i < 256n; ++i) {
expect(await this.mock[fragment](elements, 2n ** i - 1n)).to.equal(BigInt(elements.length));
expect(await this.mock[fragment](elements, 2n ** i - 1n)).to.equal(
isValueType ? BigInt(elements.length) : generators[name].zero,
);
expect(await this.mock[fragment](elements, 2n ** i + 0n)).to.equal(elements[0]);
expect(await this.mock[fragment](elements, 2n ** i + 1n)).to.equal(elements[1]);
}