EnumerableMap.test.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. const { BN, expectEvent } = require('@openzeppelin/test-helpers');
  2. const { expect } = require('chai');
  3. const zip = require('lodash.zip');
  4. const EnumerableMapMock = artifacts.require('EnumerableMapMock');
  5. contract('EnumerableMap', function (accounts) {
  6. const [ accountA, accountB, accountC ] = accounts;
  7. const keyA = new BN('7891');
  8. const keyB = new BN('451');
  9. const keyC = new BN('9592328');
  10. beforeEach(async function () {
  11. this.map = await EnumerableMapMock.new();
  12. });
  13. async function expectMembersMatch (map, keys, values) {
  14. expect(keys.length).to.equal(values.length);
  15. await Promise.all(keys.map(async key =>
  16. expect(await map.contains(key)).to.equal(true),
  17. ));
  18. expect(await map.length()).to.bignumber.equal(keys.length.toString());
  19. expect(await Promise.all(keys.map(key =>
  20. map.get(key),
  21. ))).to.have.same.members(values);
  22. // To compare key-value pairs, we zip keys and values, and convert BNs to
  23. // strings to workaround Chai limitations when dealing with nested arrays
  24. expect(await Promise.all([...Array(keys.length).keys()].map(async (index) => {
  25. const entry = await map.at(index);
  26. return [entry.key.toString(), entry.value];
  27. }))).to.have.same.deep.members(
  28. zip(keys.map(k => k.toString()), values),
  29. );
  30. }
  31. it('starts empty', async function () {
  32. expect(await this.map.contains(keyA)).to.equal(false);
  33. await expectMembersMatch(this.map, [], []);
  34. });
  35. describe('set', function () {
  36. it('adds a key', async function () {
  37. const receipt = await this.map.set(keyA, accountA);
  38. expectEvent(receipt, 'OperationResult', { result: true });
  39. await expectMembersMatch(this.map, [keyA], [accountA]);
  40. });
  41. it('adds several keys', async function () {
  42. await this.map.set(keyA, accountA);
  43. await this.map.set(keyB, accountB);
  44. await expectMembersMatch(this.map, [keyA, keyB], [accountA, accountB]);
  45. expect(await this.map.contains(keyC)).to.equal(false);
  46. });
  47. it('returns false when adding keys already in the set', async function () {
  48. await this.map.set(keyA, accountA);
  49. const receipt = (await this.map.set(keyA, accountA));
  50. expectEvent(receipt, 'OperationResult', { result: false });
  51. await expectMembersMatch(this.map, [keyA], [accountA]);
  52. });
  53. it('updates values for keys already in the set', async function () {
  54. await this.map.set(keyA, accountA);
  55. await this.map.set(keyA, accountB);
  56. await expectMembersMatch(this.map, [keyA], [accountB]);
  57. });
  58. });
  59. describe('remove', function () {
  60. it('removes added keys', async function () {
  61. await this.map.set(keyA, accountA);
  62. const receipt = await this.map.remove(keyA);
  63. expectEvent(receipt, 'OperationResult', { result: true });
  64. expect(await this.map.contains(keyA)).to.equal(false);
  65. await expectMembersMatch(this.map, [], []);
  66. });
  67. it('returns false when removing keys not in the set', async function () {
  68. const receipt = await this.map.remove(keyA);
  69. expectEvent(receipt, 'OperationResult', { result: false });
  70. expect(await this.map.contains(keyA)).to.equal(false);
  71. });
  72. it('adds and removes multiple keys', async function () {
  73. // []
  74. await this.map.set(keyA, accountA);
  75. await this.map.set(keyC, accountC);
  76. // [A, C]
  77. await this.map.remove(keyA);
  78. await this.map.remove(keyB);
  79. // [C]
  80. await this.map.set(keyB, accountB);
  81. // [C, B]
  82. await this.map.set(keyA, accountA);
  83. await this.map.remove(keyC);
  84. // [A, B]
  85. await this.map.set(keyA, accountA);
  86. await this.map.set(keyB, accountB);
  87. // [A, B]
  88. await this.map.set(keyC, accountC);
  89. await this.map.remove(keyA);
  90. // [B, C]
  91. await this.map.set(keyA, accountA);
  92. await this.map.remove(keyB);
  93. // [A, C]
  94. await expectMembersMatch(this.map, [keyA, keyC], [accountA, accountC]);
  95. expect(await this.map.contains(keyB)).to.equal(false);
  96. });
  97. });
  98. });