forked from OpenZeppelin/openzeppelin-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnumerableSet.behavior.js
More file actions
151 lines (106 loc) · 4.52 KB
/
EnumerableSet.behavior.js
File metadata and controls
151 lines (106 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const { expect } = require('chai');
const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
function shouldBehaveLikeSet() {
async function expectMembersMatch(methods, values) {
expect(await methods.length()).to.equal(values.length);
for (const value of values) expect(await methods.contains(value)).to.be.true;
expect(await Promise.all(values.map((_, index) => methods.at(index)))).to.have.deep.members(values);
expect([...(await methods.values())]).to.have.deep.members(values);
}
it('starts empty', async function () {
expect(await this.methods.contains(this.valueA)).to.be.false;
await expectMembersMatch(this.methods, []);
});
describe('add', function () {
it('adds a value', async function () {
await expect(this.methods.add(this.valueA)).to.emit(this.mock, this.events.addReturn).withArgs(true);
await expectMembersMatch(this.methods, [this.valueA]);
});
it('adds several values', async function () {
await this.methods.add(this.valueA);
await this.methods.add(this.valueB);
await expectMembersMatch(this.methods, [this.valueA, this.valueB]);
expect(await this.methods.contains(this.valueC)).to.be.false;
});
it('returns false when adding values already in the set', async function () {
await this.methods.add(this.valueA);
await expect(this.methods.add(this.valueA)).to.emit(this.mock, this.events.addReturn).withArgs(false);
await expectMembersMatch(this.methods, [this.valueA]);
});
});
describe('at', function () {
it('reverts when retrieving non-existent elements', async function () {
await expect(this.methods.at(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
});
it('retrieves existing element', async function () {
await this.methods.add(this.valueA);
expect(await this.methods.at(0)).to.deep.equal(this.valueA);
});
});
describe('remove', function () {
it('removes added values', async function () {
await this.methods.add(this.valueA);
await expect(this.methods.remove(this.valueA)).to.emit(this.mock, this.events.removeReturn).withArgs(true);
expect(await this.methods.contains(this.valueA)).to.be.false;
await expectMembersMatch(this.methods, []);
});
it('returns false when removing values not in the set', async function () {
await expect(this.methods.remove(this.valueA)).to.emit(this.mock, this.events.removeReturn).withArgs(false);
expect(await this.methods.contains(this.valueA)).to.be.false;
});
it('adds and removes multiple values', async function () {
// []
await this.methods.add(this.valueA);
await this.methods.add(this.valueC);
// [A, C]
await this.methods.remove(this.valueA);
await this.methods.remove(this.valueB);
// [C]
await this.methods.add(this.valueB);
// [C, B]
await this.methods.add(this.valueA);
await this.methods.remove(this.valueC);
// [A, B]
await this.methods.add(this.valueA);
await this.methods.add(this.valueB);
// [A, B]
await this.methods.add(this.valueC);
await this.methods.remove(this.valueA);
// [B, C]
await this.methods.add(this.valueA);
await this.methods.remove(this.valueB);
// [A, C]
await expectMembersMatch(this.methods, [this.valueA, this.valueC]);
expect(await this.methods.contains(this.valueB)).to.be.false;
});
});
describe('clear', function () {
it('clears a single item', async function () {
await this.methods.add(this.valueA);
await expect(this.methods.length()).to.eventually.equal(1);
await this.methods.clear();
await expect(this.methods.length()).to.eventually.equal(0);
});
it('clears multiple items', async function () {
await this.methods.add(this.valueA);
await this.methods.add(this.valueB);
await this.methods.add(this.valueC);
await expect(this.methods.length()).to.eventually.equal(3);
await this.methods.clear();
await expect(this.methods.length()).to.eventually.equal(0);
});
it('does not revert on empty set', async function () {
await this.methods.clear();
});
it('clear then add value', async function () {
await this.methods.add(this.valueA);
await this.methods.add(this.valueB);
await this.methods.clear();
await this.methods.add(this.valueA);
await expectMembersMatch(this.methods, [this.valueA]);
});
});
}
module.exports = {
shouldBehaveLikeSet,
};