MigratorTest.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <?php
  2. declare(strict_types=1);
  3. use PHPUnit\Framework\TestCase;
  4. class MigratorTest extends TestCase
  5. {
  6. public function testAddMigration(): void {
  7. $migrator = new Minz_Migrator();
  8. $migrator->addMigration('foo', function () {
  9. return true;
  10. });
  11. $migrations = $migrator->migrations();
  12. self::assertArrayHasKey('foo', $migrations);
  13. $result = $migrations['foo']();
  14. self::assertTrue($result);
  15. }
  16. public function testMigrationsIsSorted(): void {
  17. $migrator = new Minz_Migrator();
  18. $migrator->addMigration('2_foo', function () {
  19. return true;
  20. });
  21. $migrator->addMigration('10_foo', function () {
  22. return true;
  23. });
  24. $migrator->addMigration('1_foo', function () {
  25. return true;
  26. });
  27. $expected_versions = ['1_foo', '2_foo', '10_foo'];
  28. $migrations = $migrator->migrations();
  29. self::assertSame($expected_versions, array_keys($migrations));
  30. }
  31. public function testSetAppliedVersions(): void {
  32. $migrator = new Minz_Migrator();
  33. $migrator->addMigration('foo', function () {
  34. return true;
  35. });
  36. $migrator->setAppliedVersions(['foo']);
  37. self::assertSame(['foo'], $migrator->appliedVersions());
  38. }
  39. public function testSetAppliedVersionsTrimArgument(): void {
  40. $migrator = new Minz_Migrator();
  41. $migrator->addMigration('foo', function () {
  42. return true;
  43. });
  44. $migrator->setAppliedVersions(["foo\n"]);
  45. self::assertSame(['foo'], $migrator->appliedVersions());
  46. }
  47. public function testSetAppliedVersionsFailsIfMigrationDoesNotExist(): void {
  48. $this->expectException(DomainException::class);
  49. $this->expectExceptionMessage('foo migration does not exist.');
  50. $migrator = new Minz_Migrator();
  51. $migrator->setAppliedVersions(['foo']);
  52. }
  53. public function testVersions(): void {
  54. $migrator = new Minz_Migrator();
  55. $migrator->addMigration('foo', function () {
  56. return true;
  57. });
  58. $migrator->addMigration('bar', function () {
  59. return true;
  60. });
  61. $versions = $migrator->versions();
  62. self::assertSame(['bar', 'foo'], $versions);
  63. }
  64. public function testMigrate(): void {
  65. $migrator = new Minz_Migrator();
  66. $spy = false;
  67. $migrator->addMigration('foo', function () use (&$spy) {
  68. $spy = true;
  69. return true;
  70. });
  71. self::assertEmpty($migrator->appliedVersions());
  72. $result = $migrator->migrate();
  73. self::assertTrue($spy);
  74. self::assertSame(['foo'], $migrator->appliedVersions());
  75. self::assertSame([
  76. 'foo' => true,
  77. ], $result);
  78. }
  79. public function testMigrateCallsMigrationsInSortedOrder(): void {
  80. $migrator = new Minz_Migrator();
  81. $spy_foo_1_is_called = false;
  82. $migrator->addMigration('2_foo', function () use (&$spy_foo_1_is_called) {
  83. return $spy_foo_1_is_called;
  84. });
  85. $migrator->addMigration('1_foo', function () use (&$spy_foo_1_is_called) {
  86. $spy_foo_1_is_called = true;
  87. return true;
  88. });
  89. $result = $migrator->migrate();
  90. self::assertSame(['1_foo', '2_foo'], $migrator->appliedVersions());
  91. self::assertSame([
  92. '1_foo' => true,
  93. '2_foo' => true,
  94. ], $result);
  95. }
  96. public function testMigrateDoesNotCallAppliedMigrations(): void {
  97. $migrator = new Minz_Migrator();
  98. $spy = false;
  99. $migrator->addMigration('1_foo', function () use (&$spy) {
  100. $spy = true;
  101. return true;
  102. });
  103. $migrator->setAppliedVersions(['1_foo']);
  104. $result = $migrator->migrate();
  105. self::assertFalse($spy);
  106. self::assertSame([], $result);
  107. }
  108. public function testMigrateCallNonAppliedBetweenTwoApplied(): void {
  109. $migrator = new Minz_Migrator();
  110. $migrator->addMigration('1_foo', function () {
  111. return true;
  112. });
  113. $migrator->addMigration('2_foo', function () {
  114. return true;
  115. });
  116. $migrator->addMigration('3_foo', function () {
  117. return true;
  118. });
  119. $migrator->setAppliedVersions(['1_foo', '3_foo']);
  120. $result = $migrator->migrate();
  121. self::assertSame(['1_foo', '2_foo', '3_foo'], $migrator->appliedVersions());
  122. self::assertSame([
  123. '2_foo' => true,
  124. ], $result);
  125. }
  126. public function testMigrateWithMigrationReturningFalseDoesNotApplyVersion(): void {
  127. $migrator = new Minz_Migrator();
  128. $migrator->addMigration('1_foo', function () {
  129. return true;
  130. });
  131. $migrator->addMigration('2_foo', function () {
  132. return false;
  133. });
  134. $result = $migrator->migrate();
  135. self::assertSame(['1_foo'], $migrator->appliedVersions());
  136. self::assertSame([
  137. '1_foo' => true,
  138. '2_foo' => false,
  139. ], $result);
  140. }
  141. public function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations(): void {
  142. $migrator = new Minz_Migrator();
  143. $migrator->addMigration('1_foo', function () {
  144. return false;
  145. });
  146. $spy = false;
  147. $migrator->addMigration('2_foo', function () use (&$spy) {
  148. $spy = true;
  149. return true;
  150. });
  151. $result = $migrator->migrate();
  152. self::assertEmpty($migrator->appliedVersions());
  153. self::assertFalse($spy);
  154. self::assertSame([
  155. '1_foo' => false,
  156. ], $result);
  157. }
  158. public function testMigrateWithFailingMigration(): void {
  159. $migrator = new Minz_Migrator();
  160. $migrator->addMigration('foo', function () {
  161. throw new \Exception('Oops, it failed.');
  162. });
  163. $result = $migrator->migrate();
  164. self::assertEmpty($migrator->appliedVersions());
  165. self::assertSame([
  166. 'foo' => 'Oops, it failed.',
  167. ], $result);
  168. }
  169. public function testUpToDate(): void {
  170. $migrator = new Minz_Migrator();
  171. $migrator->addMigration('foo', function () {
  172. return true;
  173. });
  174. $migrator->setAppliedVersions(['foo']);
  175. $upToDate = $migrator->upToDate();
  176. self::assertTrue($upToDate);
  177. }
  178. public function testUpToDateIfRemainingMigration(): void {
  179. $migrator = new Minz_Migrator();
  180. $migrator->addMigration('1_foo', function () {
  181. return true;
  182. });
  183. $migrator->addMigration('2_foo', function () {
  184. return true;
  185. });
  186. $migrator->setAppliedVersions(['2_foo']);
  187. $upToDate = $migrator->upToDate();
  188. self::assertFalse($upToDate);
  189. }
  190. public function testUpToDateIfNoMigrations(): void {
  191. $migrator = new Minz_Migrator();
  192. $upToDate = $migrator->upToDate();
  193. self::assertTrue($upToDate);
  194. }
  195. public function testConstructorLoadsDirectory(): void {
  196. $migrations_path = TESTS_PATH . '/fixtures/migrations/';
  197. $migrator = new Minz_Migrator($migrations_path);
  198. $expected_versions = ['2019_12_22_FooBar', '2019_12_23_Baz'];
  199. $migrations = $migrator->migrations();
  200. self::assertSame($expected_versions, array_keys($migrations));
  201. }
  202. public function testExecute(): void {
  203. $migrations_path = TESTS_PATH . '/fixtures/migrations/';
  204. $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
  205. self::assertIsString($applied_migrations_path);
  206. $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path);
  207. self::assertTrue($result);
  208. $versions = file_get_contents($applied_migrations_path);
  209. self::assertSame("2019_12_22_FooBar\n2019_12_23_Baz", $versions);
  210. @unlink($applied_migrations_path);
  211. }
  212. public function testExecuteWithAlreadyAppliedMigration(): void {
  213. $migrations_path = TESTS_PATH . '/fixtures/migrations/';
  214. $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
  215. self::assertIsString($applied_migrations_path);
  216. file_put_contents($applied_migrations_path, '2019_12_22_FooBar');
  217. $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path);
  218. self::assertTrue($result);
  219. $versions = file_get_contents($applied_migrations_path);
  220. self::assertSame("2019_12_22_FooBar\n2019_12_23_Baz", $versions);
  221. @unlink($applied_migrations_path);
  222. }
  223. public function testExecuteWithAppliedMigrationInDifferentOrder(): void {
  224. $migrations_path = TESTS_PATH . '/fixtures/migrations/';
  225. $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
  226. self::assertIsString($applied_migrations_path);
  227. file_put_contents($applied_migrations_path, "2019_12_23_Baz\n2019_12_22_FooBar");
  228. $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path);
  229. self::assertTrue($result);
  230. $versions = file_get_contents($applied_migrations_path);
  231. // if the order changes, it probably means the first versions comparison test doesn’t work anymore
  232. self::assertSame("2019_12_23_Baz\n2019_12_22_FooBar", $versions);
  233. @unlink($applied_migrations_path);
  234. }
  235. public function testExecuteFailsIfVersionPathDoesNotExist(): void {
  236. $migrations_path = TESTS_PATH . '/fixtures/migrations/';
  237. $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
  238. $expected_result = "Cannot open the {$applied_migrations_path} file";
  239. self::assertIsString($applied_migrations_path);
  240. unlink($applied_migrations_path);
  241. $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path);
  242. self::assertSame($expected_result, $result);
  243. @unlink($applied_migrations_path);
  244. }
  245. public function testExecuteFailsIfAMigrationIsFailing(): void {
  246. $migrations_path = TESTS_PATH . '/fixtures/migrations_with_failing/';
  247. $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
  248. $expected_result = 'A migration failed to be applied, please see previous logs.';
  249. self::assertIsString($applied_migrations_path);
  250. $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path);
  251. self::assertIsString($result);
  252. [$result,] = explode("\n", $result, 2);
  253. self::assertSame($expected_result, $result);
  254. $versions = file_get_contents($applied_migrations_path);
  255. self::assertSame('2020_01_11_FooBar', $versions);
  256. @unlink($applied_migrations_path);
  257. }
  258. }