upload_to_google_storage_first_class_unittest.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #!/usr/bin/env vpython3
  2. # Copyright (c) 2024 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Unit tests for upload_to_google_storage_first_class.py."""
  6. from io import StringIO
  7. import optparse
  8. import os
  9. import posixpath
  10. import shutil
  11. import sys
  12. import tarfile
  13. import tempfile
  14. import unittest
  15. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  16. import upload_to_google_storage_first_class
  17. from download_from_google_storage_unittest import GsutilMock
  18. from download_from_google_storage_unittest import ChangedWorkingDirectory
  19. # ../third_party/gsutil/gsutil
  20. GSUTIL_DEFAULT_PATH = os.path.join(
  21. os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'third_party',
  22. 'gsutil', 'gsutil')
  23. TEST_DIR = os.path.dirname(os.path.abspath(__file__))
  24. class UploadTests(unittest.TestCase):
  25. def setUp(self):
  26. self.gsutil = GsutilMock(GSUTIL_DEFAULT_PATH, None)
  27. self.temp_dir = tempfile.mkdtemp(prefix='gstools_test')
  28. self.base_path = os.path.join(self.temp_dir, 'gstools')
  29. shutil.copytree(os.path.join(TEST_DIR, 'gstools'), self.base_path)
  30. self.base_url = 'gs://sometesturl'
  31. self.parser = optparse.OptionParser()
  32. self.lorem_ipsum = os.path.join(self.base_path, 'lorem_ipsum.txt')
  33. def tearDown(self):
  34. shutil.rmtree(self.temp_dir)
  35. sys.stdin = sys.__stdin__
  36. def test_upload_single_file_missing_generation(self):
  37. file = self.lorem_ipsum
  38. object_name = 'gs_object_name/version123'
  39. self.gsutil.add_expected(0, "", "") # ls call
  40. self.gsutil.add_expected(0, "", 'weird output') # cp call
  41. actual = upload_to_google_storage_first_class.upload_to_google_storage(
  42. file=file,
  43. base_url=self.base_url,
  44. object_name=object_name,
  45. gsutil=self.gsutil,
  46. force=True,
  47. gzip=False,
  48. dry_run=False)
  49. self.assertEqual(
  50. self.gsutil.history,
  51. [('check_call', ('ls', '%s/%s' % (self.base_url, object_name))),
  52. ('check_call',
  53. ('-h', 'Cache-Control:public, max-age=31536000', 'cp', '-v', file,
  54. '%s/%s' % (self.base_url, object_name)))])
  55. self.assertEqual(
  56. actual, upload_to_google_storage_first_class.MISSING_GENERATION_MSG)
  57. def test_upload_single_file(self):
  58. file = self.lorem_ipsum
  59. object_name = 'gs_object_name/version123'
  60. self.gsutil.add_expected(0, "", "") # ls call
  61. expected_generation = '1712070862651948'
  62. expected_cp_status = (
  63. f'Copying file://{file} [Content-Type=text/plain].\n'
  64. f'Created: {self.base_url}/{object_name}#{expected_generation}\n'
  65. 'Operation completed over 1 objects/8.0 B.')
  66. self.gsutil.add_expected(0, "", expected_cp_status) # cp call
  67. actual = upload_to_google_storage_first_class.upload_to_google_storage(
  68. file=file,
  69. base_url=self.base_url,
  70. object_name=object_name,
  71. gsutil=self.gsutil,
  72. force=True,
  73. gzip=False,
  74. dry_run=False)
  75. self.assertEqual(
  76. self.gsutil.history,
  77. [('check_call', ('ls', '%s/%s' % (self.base_url, object_name))),
  78. ('check_call',
  79. ('-h', 'Cache-Control:public, max-age=31536000', 'cp', '-v', file,
  80. '%s/%s' % (self.base_url, object_name)))])
  81. self.assertEqual(actual, expected_generation)
  82. def test_upload_single_file_remote_exists(self):
  83. file = self.lorem_ipsum
  84. object_name = 'gs_object_name/version123'
  85. etag_string = 'ETag: 634d7c1ed3545383837428f031840a1e'
  86. self.gsutil.add_expected(0, b'', b'')
  87. self.gsutil.add_expected(0, etag_string, b'')
  88. with self.assertRaises(Exception):
  89. upload_to_google_storage_first_class.upload_to_google_storage(
  90. file=file,
  91. base_url=self.base_url,
  92. object_name=object_name,
  93. gsutil=self.gsutil,
  94. force=False,
  95. gzip=False,
  96. dry_run=False)
  97. self.assertEqual(self.gsutil.history,
  98. [('check_call',
  99. ('ls', '%s/%s' % (self.base_url, object_name))),
  100. ('check_call', ('ls', '-L', '%s/%s' %
  101. (self.base_url, object_name)))])
  102. def test_create_archive(self):
  103. work_dir = os.path.join(self.base_path, 'download_test_data')
  104. with ChangedWorkingDirectory(work_dir):
  105. dirname = 'subfolder'
  106. dirs = [dirname]
  107. self.assertTrue(
  108. upload_to_google_storage_first_class.validate_archive_dirs(
  109. dirs))
  110. tar_filename = upload_to_google_storage_first_class.create_archive(
  111. dirs)
  112. with tarfile.open(tar_filename, 'r:gz') as tar:
  113. content = map(lambda x: x.name, tar.getmembers())
  114. self.assertIn(dirname, content)
  115. def test_create_archive_multiple_dirs(self):
  116. work_dir = os.path.join(self.base_path, 'download_test_data')
  117. with ChangedWorkingDirectory(work_dir):
  118. dirs = ['subfolder', 'subfolder2']
  119. self.assertTrue(
  120. upload_to_google_storage_first_class.validate_archive_dirs(
  121. dirs))
  122. tar_filename = upload_to_google_storage_first_class.create_archive(
  123. dirs)
  124. with tarfile.open(tar_filename, 'r:gz') as tar:
  125. content = map(lambda x: x.name, tar.getmembers())
  126. for dirname in dirs:
  127. self.assertIn(dirname, content)
  128. @unittest.skipIf(sys.platform == 'win32',
  129. 'os.symlink does not exist on win')
  130. def test_validate_archive_dirs_fails(self):
  131. work_dir = os.path.join(self.base_path, 'download_test_data')
  132. with ChangedWorkingDirectory(work_dir):
  133. symlink = 'link'
  134. os.symlink(os.path.join(self.base_path, 'subfolder'), symlink)
  135. self.assertFalse(
  136. upload_to_google_storage_first_class.validate_archive_dirs(
  137. [symlink]))
  138. self.assertFalse(
  139. upload_to_google_storage_first_class.validate_archive_dirs(
  140. ['foobar']))
  141. def test_dry_run(self):
  142. file = self.lorem_ipsum
  143. object_name = 'gs_object_name/version123'
  144. upload_to_google_storage_first_class.upload_to_google_storage(
  145. file=file,
  146. base_url=self.base_url,
  147. object_name=object_name,
  148. gsutil=self.gsutil,
  149. force=False,
  150. gzip=False,
  151. dry_run=True)
  152. self.assertEqual(self.gsutil.history,
  153. [('check_call',
  154. ('ls', '%s/%s' % (self.base_url, object_name))),
  155. ('check_call', ('ls', '-L', '%s/%s' %
  156. (self.base_url, object_name)))])
  157. def test_get_targets_no_args(self):
  158. try:
  159. upload_to_google_storage_first_class.get_targets([], self.parser,
  160. False)
  161. self.fail()
  162. except SystemExit as e:
  163. self.assertEqual(e.code, 2)
  164. def test_get_targets_passthrough(self):
  165. result = upload_to_google_storage_first_class.get_targets(
  166. ['a', 'b', 'c', 'd', 'e'], self.parser, False)
  167. self.assertEqual(result, ['a', 'b', 'c', 'd', 'e'])
  168. def test_get_targets_multiple_stdin(self):
  169. inputs = ['a', 'b', 'c', 'd', 'e']
  170. sys.stdin = StringIO(os.linesep.join(inputs))
  171. result = upload_to_google_storage_first_class.get_targets(['-'],
  172. self.parser,
  173. False)
  174. self.assertEqual(result, inputs)
  175. def test_get_targets_multiple_stdin_null(self):
  176. inputs = ['a', 'b', 'c', 'd', 'e']
  177. sys.stdin = StringIO('\0'.join(inputs))
  178. result = upload_to_google_storage_first_class.get_targets(['-'],
  179. self.parser,
  180. True)
  181. self.assertEqual(result, inputs)
  182. if __name__ == '__main__':
  183. unittest.main()