Initializable.test.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
  2. const { expect } = require('chai');
  3. const InitializableMock = artifacts.require('InitializableMock');
  4. const ConstructorInitializableMock = artifacts.require('ConstructorInitializableMock');
  5. const ReinitializerMock = artifacts.require('ReinitializerMock');
  6. const SampleChild = artifacts.require('SampleChild');
  7. contract('Initializable', function (accounts) {
  8. describe('basic testing without inheritance', function () {
  9. beforeEach('deploying', async function () {
  10. this.contract = await InitializableMock.new();
  11. });
  12. describe('before initialize', function () {
  13. it('initializer has not run', async function () {
  14. expect(await this.contract.initializerRan()).to.equal(false);
  15. });
  16. });
  17. describe('after initialize', function () {
  18. beforeEach('initializing', async function () {
  19. await this.contract.initialize();
  20. });
  21. it('initializer has run', async function () {
  22. expect(await this.contract.initializerRan()).to.equal(true);
  23. });
  24. it('initializer does not run again', async function () {
  25. await expectRevert(this.contract.initialize(), 'Initializable: contract is already initialized');
  26. });
  27. });
  28. describe('nested under an initializer', function () {
  29. it('initializer modifier reverts', async function () {
  30. await expectRevert(this.contract.initializerNested(), 'Initializable: contract is already initialized');
  31. });
  32. it('onlyInitializing modifier succeeds', async function () {
  33. await this.contract.onlyInitializingNested();
  34. expect(await this.contract.onlyInitializingRan()).to.equal(true);
  35. });
  36. });
  37. it('cannot call onlyInitializable function outside the scope of an initializable function', async function () {
  38. await expectRevert(this.contract.initializeOnlyInitializing(), 'Initializable: contract is not initializing');
  39. });
  40. });
  41. it('nested initializer can run during construction', async function () {
  42. const contract2 = await ConstructorInitializableMock.new();
  43. expect(await contract2.initializerRan()).to.equal(true);
  44. expect(await contract2.onlyInitializingRan()).to.equal(true);
  45. });
  46. describe('reinitialization', function () {
  47. beforeEach('deploying', async function () {
  48. this.contract = await ReinitializerMock.new();
  49. });
  50. it('can reinitialize', async function () {
  51. expect(await this.contract.counter()).to.be.bignumber.equal('0');
  52. await this.contract.initialize();
  53. expect(await this.contract.counter()).to.be.bignumber.equal('1');
  54. await this.contract.reinitialize(2);
  55. expect(await this.contract.counter()).to.be.bignumber.equal('2');
  56. await this.contract.reinitialize(3);
  57. expect(await this.contract.counter()).to.be.bignumber.equal('3');
  58. });
  59. it('can jump multiple steps', async function () {
  60. expect(await this.contract.counter()).to.be.bignumber.equal('0');
  61. await this.contract.initialize();
  62. expect(await this.contract.counter()).to.be.bignumber.equal('1');
  63. await this.contract.reinitialize(128);
  64. expect(await this.contract.counter()).to.be.bignumber.equal('2');
  65. });
  66. it('cannot nest reinitializers', async function () {
  67. expect(await this.contract.counter()).to.be.bignumber.equal('0');
  68. await expectRevert(this.contract.nestedReinitialize(2, 3), 'Initializable: contract is already initialized');
  69. await expectRevert(this.contract.nestedReinitialize(3, 2), 'Initializable: contract is already initialized');
  70. });
  71. it('can chain reinitializers', async function () {
  72. expect(await this.contract.counter()).to.be.bignumber.equal('0');
  73. await this.contract.chainReinitialize(2, 3);
  74. expect(await this.contract.counter()).to.be.bignumber.equal('2');
  75. });
  76. describe('contract locking', function () {
  77. it('prevents initialization', async function () {
  78. await this.contract.disableInitializers();
  79. await expectRevert(this.contract.initialize(), 'Initializable: contract is already initialized');
  80. });
  81. it('prevents re-initialization', async function () {
  82. await this.contract.disableInitializers();
  83. await expectRevert(this.contract.reinitialize(255), 'Initializable: contract is already initialized');
  84. });
  85. it('can lock contract after initialization', async function () {
  86. await this.contract.initialize();
  87. await this.contract.disableInitializers();
  88. await expectRevert(this.contract.reinitialize(255), 'Initializable: contract is already initialized');
  89. });
  90. });
  91. });
  92. describe('events', function () {
  93. it('constructor initialization emits event', async function () {
  94. const contract = await ConstructorInitializableMock.new();
  95. await expectEvent.inTransaction(contract.transactionHash, contract, 'Initialized', { version: '1' });
  96. });
  97. it('initialization emits event', async function () {
  98. const contract = await ReinitializerMock.new();
  99. const { receipt } = await contract.initialize();
  100. expect(receipt.logs.filter(({ event }) => event === 'Initialized').length).to.be.equal(1);
  101. expectEvent(receipt, 'Initialized', { version: '1' });
  102. });
  103. it('reinitialization emits event', async function () {
  104. const contract = await ReinitializerMock.new();
  105. const { receipt } = await contract.reinitialize(128);
  106. expect(receipt.logs.filter(({ event }) => event === 'Initialized').length).to.be.equal(1);
  107. expectEvent(receipt, 'Initialized', { version: '128' });
  108. });
  109. it('chained reinitialization emits multiple events', async function () {
  110. const contract = await ReinitializerMock.new();
  111. const { receipt } = await contract.chainReinitialize(2, 3);
  112. expect(receipt.logs.filter(({ event }) => event === 'Initialized').length).to.be.equal(2);
  113. expectEvent(receipt, 'Initialized', { version: '2' });
  114. expectEvent(receipt, 'Initialized', { version: '3' });
  115. });
  116. });
  117. describe('complex testing with inheritance', function () {
  118. const mother = '12';
  119. const gramps = '56';
  120. const father = '34';
  121. const child = '78';
  122. beforeEach('deploying', async function () {
  123. this.contract = await SampleChild.new();
  124. });
  125. beforeEach('initializing', async function () {
  126. await this.contract.initialize(mother, gramps, father, child);
  127. });
  128. it('initializes human', async function () {
  129. expect(await this.contract.isHuman()).to.be.equal(true);
  130. });
  131. it('initializes mother', async function () {
  132. expect(await this.contract.mother()).to.be.bignumber.equal(mother);
  133. });
  134. it('initializes gramps', async function () {
  135. expect(await this.contract.gramps()).to.be.bignumber.equal(gramps);
  136. });
  137. it('initializes father', async function () {
  138. expect(await this.contract.father()).to.be.bignumber.equal(father);
  139. });
  140. it('initializes child', async function () {
  141. expect(await this.contract.child()).to.be.bignumber.equal(child);
  142. });
  143. });
  144. });