EnumerableSet.behavior.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
  2. const { expect } = require('chai');
  3. function shouldBehaveLikeSet (
  4. values,
  5. methods,
  6. events,
  7. ) {
  8. const [ valueA, valueB, valueC ] = values;
  9. async function expectMembersMatch (set, values) {
  10. const contains = await Promise.all(values.map(value => methods.contains(set, value)));
  11. expect(contains.every(Boolean)).to.be.equal(true);
  12. const length = await methods.length(set);
  13. expect(length).to.bignumber.equal(values.length.toString());
  14. // To compare values we convert to strings to workaround Chai
  15. // limitations when dealing with nested arrays (required for BNs)
  16. const indexedValues = await Promise.all(Array(values.length).fill().map((_, index) => methods.at(set, index)));
  17. expect(
  18. indexedValues.map(v => v.toString()),
  19. ).to.have.same.members(
  20. values.map(v => v.toString()),
  21. );
  22. const returnedValues = await methods.values(set);
  23. expect(
  24. returnedValues.map(v => v.toString()),
  25. ).to.have.same.members(
  26. values.map(v => v.toString()),
  27. );
  28. }
  29. it('starts empty', async function () {
  30. expect(await methods.contains(this.set, valueA)).to.equal(false);
  31. await expectMembersMatch(this.set, []);
  32. });
  33. describe('add', function () {
  34. it('adds a value', async function () {
  35. const receipt = await methods.add(this.set, valueA);
  36. expectEvent(receipt, events.addReturn, { ret0: true });
  37. await expectMembersMatch(this.set, [valueA]);
  38. });
  39. it('adds several values', async function () {
  40. await methods.add(this.set, valueA);
  41. await methods.add(this.set, valueB);
  42. await expectMembersMatch(this.set, [valueA, valueB]);
  43. expect(await methods.contains(this.set, valueC)).to.equal(false);
  44. });
  45. it('returns false when adding values already in the set', async function () {
  46. await methods.add(this.set, valueA);
  47. const receipt = await methods.add(this.set, valueA);
  48. expectEvent(receipt, events.addReturn, { ret0: false });
  49. await expectMembersMatch(this.set, [valueA]);
  50. });
  51. });
  52. describe('at', function () {
  53. it('reverts when retrieving non-existent elements', async function () {
  54. await expectRevert.unspecified(methods.at(this.set, 0));
  55. });
  56. });
  57. describe('remove', function () {
  58. it('removes added values', async function () {
  59. await methods.add(this.set, valueA);
  60. const receipt = await methods.remove(this.set, valueA);
  61. expectEvent(receipt, events.removeReturn, { ret0: true });
  62. expect(await methods.contains(this.set, valueA)).to.equal(false);
  63. await expectMembersMatch(this.set, []);
  64. });
  65. it('returns false when removing values not in the set', async function () {
  66. const receipt = await methods.remove(this.set, valueA);
  67. expectEvent(receipt, events.removeReturn, { ret0: false });
  68. expect(await methods.contains(this.set, valueA)).to.equal(false);
  69. });
  70. it('adds and removes multiple values', async function () {
  71. // []
  72. await methods.add(this.set, valueA);
  73. await methods.add(this.set, valueC);
  74. // [A, C]
  75. await methods.remove(this.set, valueA);
  76. await methods.remove(this.set, valueB);
  77. // [C]
  78. await methods.add(this.set, valueB);
  79. // [C, B]
  80. await methods.add(this.set, valueA);
  81. await methods.remove(this.set, valueC);
  82. // [A, B]
  83. await methods.add(this.set, valueA);
  84. await methods.add(this.set, valueB);
  85. // [A, B]
  86. await methods.add(this.set, valueC);
  87. await methods.remove(this.set, valueA);
  88. // [B, C]
  89. await methods.add(this.set, valueA);
  90. await methods.remove(this.set, valueB);
  91. // [A, C]
  92. await expectMembersMatch(this.set, [valueA, valueC]);
  93. expect(await methods.contains(this.set, valueB)).to.equal(false);
  94. });
  95. });
  96. }
  97. module.exports = {
  98. shouldBehaveLikeSet,
  99. };