TestFileResource.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. '''
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. "License"); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. '''
  16. from unittest import TestCase
  17. from mock.mock import patch, MagicMock
  18. import os
  19. import sys
  20. import grp
  21. import pwd
  22. from resource_management.core import Environment, Fail
  23. from resource_management.core.resources import File
  24. from resource_management.core.system import System
  25. from resource_management.core import sudo
  26. import resource_management.core.providers.system
  27. import resource_management
  28. @patch.object(System, "os_family", new = 'redhat')
  29. class TestFileResource(TestCase):
  30. @patch.object(os.path, "dirname")
  31. @patch.object(sudo, "path_isdir")
  32. def test_action_create_dir_exist(self, isdir_mock, dirname_mock):
  33. """
  34. Tests if 'create' action fails when path is existent directory
  35. """
  36. isdir_mock.side_effect = [True, False]
  37. try:
  38. with Environment('/') as env:
  39. File('/existent_directory',
  40. action='create',
  41. mode=0777,
  42. content='file-content'
  43. )
  44. self.fail("Must fail when directory with name 'path' exist")
  45. except Fail as e:
  46. self.assertEqual('Applying File[\'/existent_directory\'] failed, directory with name /existent_directory exists',
  47. str(e))
  48. self.assertFalse(dirname_mock.called)
  49. @patch.object(os.path, "dirname")
  50. @patch.object(sudo, "path_isdir")
  51. def test_action_create_parent_dir_non_exist(self, isdir_mock, dirname_mock):
  52. """
  53. Tests if 'create' action fails when parent directory of path
  54. doesn't exist
  55. """
  56. isdir_mock.side_effect = [False, False]
  57. dirname_mock.return_value = "/non_existent_directory"
  58. try:
  59. with Environment('/') as env:
  60. File('/non_existent_directory/file',
  61. action='create',
  62. mode=0777,
  63. content='file-content'
  64. )
  65. self.fail('Must fail on non existent parent directory')
  66. except Fail as e:
  67. self.assertEqual(
  68. 'Applying File[\'/non_existent_directory/file\'] failed, parent directory /non_existent_directory doesn\'t exist',
  69. str(e))
  70. self.assertTrue(dirname_mock.called)
  71. @patch("resource_management.core.providers.system._ensure_metadata")
  72. @patch.object(sudo, "read_file")
  73. @patch.object(sudo, "create_file")
  74. @patch.object(sudo, "path_exists")
  75. @patch.object(sudo, "path_isdir")
  76. def test_action_create_non_existent_file(self, isdir_mock, exists_mock, create_file_mock, read_file_mock, ensure_mock):
  77. """
  78. Tests if 'create' action create new non existent file and write proper data
  79. """
  80. isdir_mock.side_effect = [False, True]
  81. exists_mock.return_value = False
  82. with Environment('/') as env:
  83. File('/directory/file',
  84. action='create',
  85. mode=0777,
  86. content='file-content'
  87. )
  88. create_file_mock.assert_called_with('/directory/file', 'file-content', encoding=None)
  89. self.assertEqual(create_file_mock.call_count, 1)
  90. ensure_mock.assert_called()
  91. @patch("resource_management.core.providers.system._ensure_metadata")
  92. @patch.object(sudo, "read_file")
  93. @patch.object(sudo, "create_file")
  94. @patch.object(sudo, "path_exists")
  95. @patch.object(sudo, "path_isdir")
  96. def test_action_create_replace(self, isdir_mock, exists_mock, create_file_mock, read_file_mock, ensure_mock):
  97. """
  98. Tests if 'create' action rewrite existent file with new data
  99. """
  100. isdir_mock.side_effect = [False, True]
  101. exists_mock.return_value = True
  102. with Environment('/') as env:
  103. File('/directory/file',
  104. action='create',
  105. mode=0777,
  106. backup=False,
  107. content='new-content'
  108. )
  109. read_file_mock.assert_called_with('/directory/file', encoding=None)
  110. create_file_mock.assert_called_with('/directory/file', 'new-content', encoding=None)
  111. @patch.object(sudo, "unlink")
  112. @patch.object(sudo, "path_exists")
  113. @patch.object(sudo, "path_isdir")
  114. def test_action_delete_is_directory(self, isdir_mock, exist_mock, unlink_mock):
  115. """
  116. Tests if 'delete' action fails when path is directory
  117. """
  118. isdir_mock.return_value = True
  119. try:
  120. with Environment('/') as env:
  121. File('/directory/file',
  122. action='delete',
  123. mode=0777,
  124. backup=False,
  125. content='new-content'
  126. )
  127. self.fail("Should fail when deleting directory")
  128. except Fail:
  129. pass
  130. self.assertEqual(isdir_mock.call_count, 1)
  131. self.assertEqual(exist_mock.call_count, 0)
  132. self.assertEqual(unlink_mock.call_count, 0)
  133. @patch.object(sudo, "unlink")
  134. @patch.object(sudo, "path_exists")
  135. @patch.object(sudo, "path_isdir")
  136. def test_action_delete(self, isdir_mock, exist_mock, unlink_mock):
  137. """
  138. Tests if 'delete' action removes file
  139. """
  140. isdir_mock.return_value = False
  141. with Environment('/') as env:
  142. File('/directory/file',
  143. action='delete',
  144. mode=0777,
  145. backup=False,
  146. content='new-content'
  147. )
  148. self.assertEqual(isdir_mock.call_count, 1)
  149. self.assertEqual(exist_mock.call_count, 1)
  150. self.assertEqual(unlink_mock.call_count, 1)
  151. @patch.object(sudo, "path_isdir")
  152. def test_attribute_path(self, isdir_mock):
  153. """
  154. Tests 'path' attribute
  155. """
  156. isdir_mock.side_effect = [True, False]
  157. try:
  158. with Environment('/') as env:
  159. File('/existent_directory',
  160. action='create',
  161. mode=0777,
  162. content='file-content'
  163. )
  164. self.fail("Must fail when directory with name 'path' exist")
  165. except Fail as e:
  166. pass
  167. isdir_mock.assert_called_with('/existent_directory')
  168. @patch.object(resource_management.core.Environment, "backup_file")
  169. @patch("resource_management.core.providers.system._ensure_metadata")
  170. @patch.object(sudo, "read_file")
  171. @patch.object(sudo, "create_file")
  172. @patch.object(sudo, "path_exists")
  173. @patch.object(sudo, "path_isdir")
  174. def test_attribute_backup(self, isdir_mock, exists_mock, create_file_mock, read_file_mock, ensure_mock, backup_file_mock):
  175. """
  176. Tests 'backup' attribute
  177. """
  178. isdir_mock.side_effect = [False, True, False, True]
  179. exists_mock.return_value = True
  180. with Environment('/') as env:
  181. File('/directory/file',
  182. action='create',
  183. mode=0777,
  184. backup=False,
  185. content='new-content'
  186. )
  187. self.assertEqual(backup_file_mock.call_count, 0)
  188. with Environment('/') as env:
  189. File('/directory/file',
  190. action='create',
  191. mode=0777,
  192. backup=True,
  193. content='new-content'
  194. )
  195. self.assertEqual(backup_file_mock.call_count, 1)
  196. backup_file_mock.assert_called_with('/directory/file')
  197. @patch("resource_management.core.providers.system._ensure_metadata")
  198. @patch("__builtin__.open")
  199. @patch.object(sudo, "path_exists")
  200. @patch.object(sudo, "path_isdir")
  201. def test_attribute_replace(self, isdir_mock, exists_mock, open_mock, ensure_mock):
  202. """
  203. Tests 'replace' attribute
  204. """
  205. isdir_mock.side_effect = [False, True]
  206. old_file, new_file = MagicMock(), MagicMock()
  207. open_mock.side_effect = [old_file, new_file]
  208. old_file.read.return_value = 'old-content'
  209. exists_mock.return_value = True
  210. with Environment('/') as env:
  211. File('/directory/file',
  212. action='create',
  213. mode=0777,
  214. backup=False,
  215. content='new-content',
  216. replace=False
  217. )
  218. old_file.read.assert_called()
  219. self.assertEqual(new_file.__enter__().write.call_count, 0)
  220. ensure_mock.assert_called()
  221. self.assertEqual(open_mock.call_count, 0)
  222. @patch.object(pwd, "getpwnam")
  223. @patch.object(grp, "getgrnam")
  224. @patch.object(sudo, "chown")
  225. @patch.object(sudo, "chmod")
  226. @patch.object(sudo, "stat")
  227. @patch.object(sudo, "create_file")
  228. @patch.object(sudo, "path_exists")
  229. @patch.object(sudo, "path_isdir")
  230. def test_ensure_metadata(self, isdir_mock, exists_mock, create_file_mock, stat_mock, chmod_mock, chown_mock, getgrnam_mock,
  231. getpwnam_mock):
  232. """
  233. Tests if _ensure_metadata changes owner, usergroup and permissions of file to proper values
  234. """
  235. isdir_mock.side_effect = [False, True, False, True]
  236. exists_mock.return_value = False
  237. class stat():
  238. def __init__(self):
  239. self.st_mode = 0666
  240. self.st_uid = 1
  241. self.st_gid = 1
  242. stat_mock.return_value = stat()
  243. getpwnam_mock.return_value = MagicMock()
  244. getpwnam_mock.return_value.pw_uid = 0
  245. getgrnam_mock.return_value = MagicMock()
  246. getgrnam_mock.return_value.gr_gid = 0
  247. with Environment('/') as env:
  248. File('/directory/file',
  249. action='create',
  250. mode=0777,
  251. content='file-content',
  252. owner='root',
  253. group='hdfs'
  254. )
  255. create_file_mock.assert_called_with('/directory/file', 'file-content', encoding=None)
  256. self.assertEqual(create_file_mock.call_count, 1)
  257. stat_mock.assert_called_with('/directory/file')
  258. self.assertEqual(chmod_mock.call_count, 1)
  259. self.assertEqual(chown_mock.call_count, 1)
  260. getgrnam_mock.assert_called_once_with('hdfs')
  261. getpwnam_mock.assert_called_with('root')
  262. chmod_mock.reset_mock()
  263. chown_mock.reset_mock()
  264. getpwnam_mock.return_value = MagicMock()
  265. getpwnam_mock.return_value.pw_uid = 1
  266. getgrnam_mock.return_value = MagicMock()
  267. getgrnam_mock.return_value.gr_gid = 1
  268. with Environment('/') as env:
  269. File('/directory/file',
  270. action='create',
  271. mode=0777,
  272. content='file-content',
  273. owner='root',
  274. group='hdfs'
  275. )
  276. self.assertEqual(chmod_mock.call_count, 1)
  277. chown_mock.assert_called_with('/directory/file', None, None)
  278. @patch("resource_management.core.providers.system._ensure_metadata")
  279. @patch("resource_management.core.providers.system.FileProvider._get_content")
  280. @patch.object(sudo, "read_file")
  281. @patch.object(sudo, "create_file")
  282. @patch.object(sudo, "path_exists")
  283. @patch.object(sudo, "path_isdir")
  284. def test_action_create_encoding(self, isdir_mock, exists_mock, create_file_mock, read_file_mock, get_content_mock ,ensure_mock):
  285. isdir_mock.side_effect = [False, True]
  286. content_mock = MagicMock()
  287. old_content_mock = MagicMock()
  288. get_content_mock.return_value = content_mock
  289. read_file_mock.return_value = old_content_mock
  290. exists_mock.return_value = True
  291. with Environment('/') as env:
  292. File('/directory/file',
  293. action='create',
  294. mode=0777,
  295. content='file-content',
  296. encoding = "UTF-8"
  297. )
  298. read_file_mock.assert_called_with('/directory/file', encoding='UTF-8')