test_migrate_cli.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. # Copyright 2021-2025 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. import filecmp
  12. import os
  13. import shutil
  14. from unittest.mock import patch
  15. import mongomock
  16. import pytest
  17. from taipy._entrypoint import _entrypoint
  18. from taipy.core._entity._migrate_cli import _MigrateCLI
  19. def test_migrate_cli_with_wrong_repository_type_arguments(caplog):
  20. with patch("sys.argv", ["prog", "migrate", "--reposiory-tyep", "filesystem"]):
  21. with pytest.raises(SystemExit):
  22. _entrypoint()
  23. assert "Unknown arguments: --reposiory-tyep. Did you mean: --repository-type?" in caplog.text
  24. def test_migrate_cli_with_wrong_skip_backup_arguments(caplog):
  25. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", "--slip-backup"]):
  26. with pytest.raises(SystemExit):
  27. _entrypoint()
  28. assert "Unknown arguments: --slip-backup. Did you mean: --skip-backup?" in caplog.text
  29. @pytest.fixture(scope="function", autouse=True)
  30. def clean_data_folder():
  31. if os.path.exists("tests/core/_entity/.data"):
  32. shutil.rmtree("tests/core/_entity/.data")
  33. if os.path.exists("tests/core/_entity/.taipy"):
  34. shutil.rmtree("tests/core/_entity/.taipy")
  35. yield
  36. def test_migrate_fs_default(caplog):
  37. _MigrateCLI.create_parser()
  38. # Test migrate with default .data folder
  39. with pytest.raises(SystemExit):
  40. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", "--skip-backup"]):
  41. _MigrateCLI.handle_command()
  42. assert "Starting entity migration from '.taipy/' folder" in caplog.text
  43. def test_migrate_fs_specified_folder(caplog, mocker):
  44. mocker.patch("taipy.core._entity._migrate._utils.version", return_value="3.1.0")
  45. _MigrateCLI.create_parser()
  46. # Copy data_sample to .data folder for testing
  47. data_sample_path = "tests/core/_entity/data_sample"
  48. data_path = "tests/core/_entity/.data"
  49. shutil.copytree(data_sample_path, data_path)
  50. # Run with --skip-backup to only test the migration
  51. with pytest.raises(SystemExit):
  52. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path, "--skip-backup"]):
  53. _MigrateCLI.handle_command()
  54. assert f"Starting entity migration from '{data_path}' folder" in caplog.text
  55. # Compare migrated .data folder with data_sample_migrated
  56. dircmp_result = filecmp.dircmp(data_path, "tests/core/_entity/data_sample_migrated")
  57. assert not dircmp_result.diff_files and not dircmp_result.left_only and not dircmp_result.right_only
  58. for subdir in dircmp_result.subdirs.values():
  59. assert not subdir.diff_files and not subdir.left_only and not subdir.right_only
  60. def test_migrate_fs_backup_and_remove(caplog, mocker):
  61. mocker.patch("taipy.core._entity._migrate._utils.version", return_value="3.1.0")
  62. _MigrateCLI.create_parser()
  63. # Copy data_sample to .data folder for testing
  64. data_sample_path = "tests/core/_entity/data_sample"
  65. data_path = "tests/core/_entity/.data"
  66. backup_path = "tests/core/_entity/.data_backup"
  67. shutil.copytree(data_sample_path, data_path)
  68. # Remove backup when it does not exist should raise an error
  69. with pytest.raises(SystemExit) as err:
  70. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path, "--remove-backup"]):
  71. _MigrateCLI.handle_command()
  72. assert err.value.code == 1
  73. assert f"The backup folder '{backup_path}' does not exist." in caplog.text
  74. assert not os.path.exists(backup_path)
  75. # Run without --skip-backup to create the backup folder
  76. with pytest.raises(SystemExit):
  77. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path]):
  78. _MigrateCLI.handle_command()
  79. assert f"Backed up entities from '{data_path}' to '{backup_path}' folder before migration." in caplog.text
  80. assert os.path.exists(backup_path)
  81. # Remove backup
  82. with pytest.raises(SystemExit):
  83. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path, "--remove-backup"]):
  84. _MigrateCLI.handle_command()
  85. assert f"Removed backup entities from the backup folder '{backup_path}'." in caplog.text
  86. assert not os.path.exists(backup_path)
  87. def test_migrate_fs_backup_and_restore(caplog, mocker):
  88. mocker.patch("taipy.core._entity._migrate._utils.version", return_value="3.1.0")
  89. _MigrateCLI.create_parser()
  90. # Copy data_sample to .data folder for testing
  91. data_sample_path = "tests/core/_entity/data_sample"
  92. data_path = "tests/core/_entity/.data"
  93. backup_path = "tests/core/_entity/.data_backup"
  94. shutil.copytree(data_sample_path, data_path)
  95. # Restore backup when it does not exist should raise an error
  96. with pytest.raises(SystemExit) as err:
  97. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path, "--restore"]):
  98. _MigrateCLI.handle_command()
  99. assert err.value.code == 1
  100. assert f"The backup folder '{backup_path}' does not exist." in caplog.text
  101. assert not os.path.exists(backup_path)
  102. # Run without --skip-backup to create the backup folder
  103. with pytest.raises(SystemExit):
  104. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path]):
  105. _MigrateCLI.handle_command()
  106. assert os.path.exists(backup_path)
  107. # restore the backup
  108. with pytest.raises(SystemExit):
  109. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", data_path, "--restore"]):
  110. _MigrateCLI.handle_command()
  111. assert f"Restored entities from the backup folder '{backup_path}' to '{data_path}'." in caplog.text
  112. assert not os.path.exists(backup_path)
  113. # Compare migrated .data folder with data_sample to ensure restoring the backup worked
  114. dircmp_result = filecmp.dircmp(data_path, "tests/core/_entity/data_sample")
  115. assert not dircmp_result.diff_files and not dircmp_result.left_only and not dircmp_result.right_only
  116. for subdir in dircmp_result.subdirs.values():
  117. assert not subdir.diff_files and not subdir.left_only and not subdir.right_only
  118. def test_migrate_fs_non_existing_folder(caplog):
  119. _MigrateCLI.create_parser()
  120. # Test migrate with a non-existing folder
  121. with pytest.raises(SystemExit) as err:
  122. with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", "non-existing-folder"]):
  123. _MigrateCLI.handle_command()
  124. assert err.value.code == 1
  125. assert "Folder 'non-existing-folder' does not exist." in caplog.text
  126. @patch("taipy.core._entity._migrate_cli._migrate_mongo_entities")
  127. def test_call_to_migrate_mongo(_migrate_mongo_entities_mock):
  128. _MigrateCLI.create_parser()
  129. with pytest.raises(SystemExit):
  130. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo"]):
  131. _MigrateCLI.handle_command()
  132. assert _migrate_mongo_entities_mock.assert_called_once_with()
  133. with pytest.raises(SystemExit):
  134. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo", "host", "port", "user", "password"]):
  135. _MigrateCLI.handle_command()
  136. assert _migrate_mongo_entities_mock.assert_called_once_with("host", "port", "user", "password")
  137. @mongomock.patch(servers=(("localhost", 27017),))
  138. def test_migrate_mongo_backup_and_remove(caplog):
  139. _MigrateCLI.create_parser()
  140. mongo_backup_path = ".mongo_backup"
  141. # Remove backup when it does not exist should raise an error
  142. with pytest.raises(SystemExit) as err:
  143. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo", "--remove-backup"]):
  144. _MigrateCLI.handle_command()
  145. assert err.value.code == 1
  146. assert f"The backup folder '{mongo_backup_path}' does not exist." in caplog.text
  147. assert not os.path.exists(mongo_backup_path)
  148. # Run without --skip-backup to create the backup database
  149. with pytest.raises(SystemExit):
  150. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo"]):
  151. _MigrateCLI.handle_command()
  152. assert os.path.exists(mongo_backup_path)
  153. # Remove backup
  154. with pytest.raises(SystemExit):
  155. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo", "--remove-backup"]):
  156. _MigrateCLI.handle_command()
  157. assert f"Removed backup entities from the backup folder '{mongo_backup_path}'." in caplog.text
  158. assert not os.path.exists(mongo_backup_path)
  159. @mongomock.patch(servers=(("localhost", 27017),))
  160. def test_migrate_mongo_backup_and_restore(caplog):
  161. _MigrateCLI.create_parser()
  162. mongo_backup_path = ".mongo_backup"
  163. # Restore backup when it does not exist should raise an error
  164. with pytest.raises(SystemExit) as err:
  165. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo", "--restore"]):
  166. _MigrateCLI.handle_command()
  167. assert err.value.code == 1
  168. assert f"The backup folder '{mongo_backup_path}' does not exist." in caplog.text
  169. assert not os.path.exists(mongo_backup_path)
  170. # Run without --skip-backup to create the backup database
  171. with pytest.raises(SystemExit):
  172. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo"]):
  173. _MigrateCLI.handle_command()
  174. assert os.path.exists(mongo_backup_path)
  175. # Restore the backup
  176. with pytest.raises(SystemExit):
  177. with patch("sys.argv", ["prog", "migrate", "--repository-type", "mongo", "--restore"]):
  178. _MigrateCLI.handle_command()
  179. assert f"Restored entities from the backup folder '{mongo_backup_path}'." in caplog.text
  180. assert not os.path.exists(mongo_backup_path)
  181. def test_not_provide_valid_repository_type(caplog):
  182. _MigrateCLI.create_parser()
  183. with pytest.raises(SystemExit):
  184. with patch("sys.argv", ["prog", "migrate"]):
  185. _MigrateCLI.handle_command()
  186. assert "the following arguments are required: --repository-type" in caplog.text
  187. with pytest.raises(SystemExit):
  188. with patch("sys.argv", ["prog", "migrate", "--repository-type"]):
  189. _MigrateCLI.handle_command()
  190. assert "argument --repository-type: expected at least one argument" in caplog.text
  191. with pytest.raises(SystemExit):
  192. with patch("sys.argv", ["prog", "migrate", "--repository-type", "invalid-repository-type"]):
  193. _MigrateCLI.handle_command()
  194. assert "Unknown repository type invalid-repository-type" in caplog.text