OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 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 # pylint: disable=W0212 |
| 6 |
| 7 """Unit tests for download_from_google_storage.py.""" |
| 8 |
| 9 import optparse |
| 10 import os |
| 11 import Queue |
| 12 import shutil |
| 13 import sys |
| 14 import tempfile |
| 15 import threading |
| 16 import unittest |
| 17 |
| 18 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| 19 |
| 20 import upload_to_google_storage |
| 21 import download_from_google_storage |
| 22 |
| 23 # ../third_party/gsutil/gsutil |
| 24 GSUTIL_DEFAULT_PATH = os.path.join( |
| 25 os.path.dirname(os.path.dirname(os.path.abspath(__file__))), |
| 26 'third_party', 'gsutil', 'gsutil') |
| 27 TEST_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 28 |
| 29 |
| 30 class GsutilMock(object): |
| 31 def __init__(self, path, boto_path=None, timeout=None): |
| 32 self.path = path |
| 33 self.timeout = timeout |
| 34 self.boto_path = boto_path |
| 35 self.expected = [] |
| 36 self.history = [] |
| 37 self.lock = threading.Lock() |
| 38 |
| 39 def add_expected(self, return_code, out, err): |
| 40 self.expected.append((return_code, out, err)) |
| 41 |
| 42 def append_history(self, method, args): |
| 43 self.history.append((method, args)) |
| 44 |
| 45 def call(self, *args): |
| 46 with self.lock: |
| 47 self.append_history('call', args) |
| 48 if self.expected: |
| 49 return self.expected.pop(0)[0] |
| 50 else: |
| 51 return 0 |
| 52 |
| 53 def check_call(self, *args): |
| 54 with self.lock: |
| 55 self.append_history('check_call', args) |
| 56 if self.expected: |
| 57 return self.expected.pop(0) |
| 58 else: |
| 59 return (0, '', '') |
| 60 |
| 61 |
| 62 class GstoolsUnitTests(unittest.TestCase): |
| 63 def setUp(self): |
| 64 self.temp_dir = tempfile.mkdtemp(prefix='gstools_test') |
| 65 self.base_path = os.path.join(self.temp_dir, 'test_files') |
| 66 shutil.copytree(os.path.join(TEST_DIR, 'gstools'), self.base_path) |
| 67 |
| 68 def cleanUp(self): |
| 69 shutil.rmtree(self.temp_dir) |
| 70 |
| 71 def test_gsutil(self): |
| 72 gsutil = download_from_google_storage.Gsutil(GSUTIL_DEFAULT_PATH) |
| 73 self.assertEqual(gsutil.path, GSUTIL_DEFAULT_PATH) |
| 74 code, _, err = gsutil.check_call() |
| 75 self.assertEqual(code, 0) |
| 76 self.assertEqual(err, '') |
| 77 |
| 78 def test_gsutil_version(self): |
| 79 gsutil = download_from_google_storage.Gsutil(GSUTIL_DEFAULT_PATH) |
| 80 _, _, err = gsutil.check_call('version') |
| 81 err_lines = err.splitlines() |
| 82 self.assertEqual(err_lines[0], 'gsutil version 3.25') |
| 83 self.assertEqual( |
| 84 err_lines[1], |
| 85 'checksum ce71ac982f1148315e7fa65cff2f83e8 (OK)') |
| 86 |
| 87 def test_get_sha1(self): |
| 88 lorem_ipsum = os.path.join(self.base_path, 'lorem_ipsum.txt') |
| 89 self.assertEqual( |
| 90 download_from_google_storage.get_sha1(lorem_ipsum), |
| 91 '7871c8e24da15bad8b0be2c36edc9dc77e37727f') |
| 92 |
| 93 def test_get_md5(self): |
| 94 lorem_ipsum = os.path.join(self.base_path, 'lorem_ipsum.txt') |
| 95 self.assertEqual( |
| 96 upload_to_google_storage.get_md5(lorem_ipsum), |
| 97 '634d7c1ed3545383837428f031840a1e') |
| 98 |
| 99 def test_get_md5_cached_read(self): |
| 100 lorem_ipsum = os.path.join(self.base_path, 'lorem_ipsum.txt') |
| 101 # Use a fake 'stale' MD5 sum. Expected behavior is to return stale sum. |
| 102 self.assertEqual( |
| 103 upload_to_google_storage.get_md5_cached(lorem_ipsum), |
| 104 '734d7c1ed3545383837428f031840a1e') |
| 105 |
| 106 def test_get_md5_cached_write(self): |
| 107 lorem_ipsum2 = os.path.join(self.base_path, 'lorem_ipsum2.txt') |
| 108 lorem_ipsum2_md5 = os.path.join(self.base_path, 'lorem_ipsum2.txt.md5') |
| 109 if os.path.exists(lorem_ipsum2_md5): |
| 110 os.remove(lorem_ipsum2_md5) |
| 111 # Use a fake 'stale' MD5 sum. Expected behavior is to return stale sum. |
| 112 self.assertEqual( |
| 113 upload_to_google_storage.get_md5_cached(lorem_ipsum2), |
| 114 '4c02d1eb455a0f22c575265d17b84b6d') |
| 115 self.assertTrue(os.path.exists(lorem_ipsum2_md5)) |
| 116 self.assertEqual( |
| 117 open(lorem_ipsum2_md5, 'rb').read(), |
| 118 '4c02d1eb455a0f22c575265d17b84b6d') |
| 119 os.remove(lorem_ipsum2_md5) # Clean up. |
| 120 self.assertFalse(os.path.exists(lorem_ipsum2_md5)) |
| 121 |
| 122 |
| 123 class DownloadTests(unittest.TestCase): |
| 124 def setUp(self): |
| 125 self.gsutil = GsutilMock(GSUTIL_DEFAULT_PATH) |
| 126 self.temp_dir = tempfile.mkdtemp(prefix='gstools_test') |
| 127 self.checkout_test_files = os.path.join( |
| 128 TEST_DIR, 'gstools', 'download_test_data') |
| 129 self.base_path = os.path.join( |
| 130 self.temp_dir, 'download_test_data') |
| 131 shutil.copytree(self.checkout_test_files, self.base_path) |
| 132 self.base_url = 'gs://sometesturl' |
| 133 self.parser = optparse.OptionParser() |
| 134 self.queue = Queue.Queue() |
| 135 self.ret_codes = Queue.Queue() |
| 136 self.lorem_ipsum = os.path.join(self.base_path, 'lorem_ipsum.txt') |
| 137 self.lorem_ipsum_sha1 = '7871c8e24da15bad8b0be2c36edc9dc77e37727f' |
| 138 self.maxDiff = None |
| 139 |
| 140 def cleanUp(self): |
| 141 shutil.rmtree(self.temp_dir) |
| 142 |
| 143 def test_enumerate_files_non_recursive(self): |
| 144 queue_size = download_from_google_storage.enumerate_work_queue( |
| 145 self.base_path, self.queue, True, False, False, None, False) |
| 146 expected_queue = [ |
| 147 ('e6c4fbd4fe7607f3e6ebf68b2ea4ef694da7b4fe', |
| 148 os.path.join(self.base_path, 'rootfolder_text.txt')), |
| 149 ('7871c8e24da15bad8b0be2c36edc9dc77e37727f', |
| 150 os.path.join(self.base_path, 'uploaded_lorem_ipsum.txt'))] |
| 151 self.assertEqual(sorted(expected_queue), sorted(self.queue.queue)) |
| 152 self.assertEqual(queue_size, 2) |
| 153 |
| 154 def test_enumerate_files_recursive(self): |
| 155 queue_size = download_from_google_storage.enumerate_work_queue( |
| 156 self.base_path, self.queue, True, True, False, None, False) |
| 157 expected_queue = [ |
| 158 ('e6c4fbd4fe7607f3e6ebf68b2ea4ef694da7b4fe', |
| 159 os.path.join(self.base_path, 'rootfolder_text.txt')), |
| 160 ('7871c8e24da15bad8b0be2c36edc9dc77e37727f', |
| 161 os.path.join(self.base_path, 'uploaded_lorem_ipsum.txt')), |
| 162 ('b5415aa0b64006a95c0c409182e628881d6d6463', |
| 163 os.path.join(self.base_path, 'subfolder', 'subfolder_text.txt'))] |
| 164 self.assertEqual(sorted(expected_queue), sorted(self.queue.queue)) |
| 165 self.assertEqual(queue_size, 3) |
| 166 |
| 167 def test_download_worker_single_file(self): |
| 168 sha1_hash = '7871c8e24da15bad8b0be2c36edc9dc77e37727f' |
| 169 input_filename = '%s/%s' % (self.base_url, sha1_hash) |
| 170 output_filename = os.path.join(self.base_path, 'uploaded_lorem_ipsum.txt') |
| 171 self.queue.put((sha1_hash, output_filename)) |
| 172 self.queue.put((None, None)) |
| 173 stdout_queue = Queue.Queue() |
| 174 download_from_google_storage._downloader_worker_thread( |
| 175 0, self.queue, False, self.base_url, self.gsutil, |
| 176 stdout_queue, self.ret_codes) |
| 177 expected_calls = [ |
| 178 ('check_call', |
| 179 ('ls', input_filename)), |
| 180 ('check_call', |
| 181 ('cp', '-q', input_filename, output_filename))] |
| 182 expected_output = [ |
| 183 '0> Downloading %s...' % output_filename] |
| 184 expected_ret_codes = [] |
| 185 self.assertEqual(list(stdout_queue.queue), expected_output) |
| 186 self.assertEqual(self.gsutil.history, expected_calls) |
| 187 self.assertEqual(list(self.ret_codes.queue), expected_ret_codes) |
| 188 |
| 189 def test_download_worker_skips_file(self): |
| 190 sha1_hash = 'e6c4fbd4fe7607f3e6ebf68b2ea4ef694da7b4fe' |
| 191 output_filename = os.path.join(self.base_path, 'rootfolder_text.txt') |
| 192 self.queue.put((sha1_hash, output_filename)) |
| 193 self.queue.put((None, None)) |
| 194 stdout_queue = Queue.Queue() |
| 195 download_from_google_storage._downloader_worker_thread( |
| 196 0, self.queue, False, self.base_url, self.gsutil, |
| 197 stdout_queue, self.ret_codes) |
| 198 expected_output = [ |
| 199 '0> File %s exists and SHA1 matches. Skipping.' % output_filename |
| 200 ] |
| 201 self.assertEqual(list(stdout_queue.queue), expected_output) |
| 202 self.assertEqual(self.gsutil.history, []) |
| 203 |
| 204 def test_download_worker_skips_not_found_file(self): |
| 205 sha1_hash = '7871c8e24da15bad8b0be2c36edc9dc77e37727f' |
| 206 input_filename = '%s/%s' % (self.base_url, sha1_hash) |
| 207 output_filename = os.path.join(self.base_path, 'uploaded_lorem_ipsum.txt') |
| 208 self.queue.put((sha1_hash, output_filename)) |
| 209 self.queue.put((None, None)) |
| 210 stdout_queue = Queue.Queue() |
| 211 self.gsutil.add_expected(1, '', '') # Return error when 'ls' is called. |
| 212 download_from_google_storage._downloader_worker_thread( |
| 213 0, self.queue, False, self.base_url, self.gsutil, |
| 214 stdout_queue, self.ret_codes) |
| 215 expected_output = [ |
| 216 '0> File %s for %s does not exist, skipping.' % ( |
| 217 input_filename, output_filename), |
| 218 ] |
| 219 expected_calls = [ |
| 220 ('check_call', |
| 221 ('ls', input_filename)) |
| 222 ] |
| 223 expected_ret_codes = [ |
| 224 (1, 'File %s for %s does not exist.' % ( |
| 225 input_filename, output_filename)) |
| 226 ] |
| 227 self.assertEqual(list(stdout_queue.queue), expected_output) |
| 228 self.assertEqual(self.gsutil.history, expected_calls) |
| 229 self.assertEqual(list(self.ret_codes.queue), expected_ret_codes) |
| 230 |
| 231 def test_download_cp_fails(self): |
| 232 sha1_hash = '7871c8e24da15bad8b0be2c36edc9dc77e37727f' |
| 233 input_filename = '%s/%s' % (self.base_url, sha1_hash) |
| 234 output_filename = os.path.join(self.base_path, 'uploaded_lorem_ipsum.txt') |
| 235 self.gsutil.add_expected(0, '', '') |
| 236 self.gsutil.add_expected(101, '', 'Test error message.') |
| 237 code = download_from_google_storage.download_from_google_storage( |
| 238 input_filename=sha1_hash, |
| 239 base_url=self.base_url, |
| 240 gsutil=self.gsutil, |
| 241 num_threads=1, |
| 242 directory=False, |
| 243 recursive=False, |
| 244 force=True, |
| 245 output=output_filename, |
| 246 ignore_errors=False, |
| 247 sha1_file=False) |
| 248 expected_calls = [ |
| 249 ('check_call', |
| 250 ('ls', input_filename)), |
| 251 ('check_call', |
| 252 ('cp', '-q', input_filename, output_filename)) |
| 253 ] |
| 254 self.assertEqual(self.gsutil.history, expected_calls) |
| 255 self.assertEqual(code, 101) |
| 256 |
| 257 def test_download_directory_no_recursive_non_force(self): |
| 258 sha1_hash = '7871c8e24da15bad8b0be2c36edc9dc77e37727f' |
| 259 input_filename = '%s/%s' % (self.base_url, sha1_hash) |
| 260 output_filename = os.path.join(self.base_path, 'uploaded_lorem_ipsum.txt') |
| 261 code = download_from_google_storage.download_from_google_storage( |
| 262 input_filename=self.base_path, |
| 263 base_url=self.base_url, |
| 264 gsutil=self.gsutil, |
| 265 num_threads=1, |
| 266 directory=True, |
| 267 recursive=False, |
| 268 force=False, |
| 269 output=None, |
| 270 ignore_errors=False, |
| 271 sha1_file=False) |
| 272 expected_calls = [ |
| 273 ('check_call', |
| 274 ('ls', input_filename)), |
| 275 ('check_call', |
| 276 ('cp', '-q', input_filename, output_filename))] |
| 277 self.assertEqual(self.gsutil.history, expected_calls) |
| 278 self.assertEqual(code, 0) |
| 279 |
| 280 |
| 281 if __name__ == '__main__': |
| 282 unittest.main() |
OLD | NEW |