blob: cd81291046b691e29af7997b49d6271e3f26d065 [file] [log] [blame]
Edward Lemur83aafc92019-11-25 23:25:05 +00001#!/usr/bin/env vpython3
hinoka@chromium.org7a790542014-12-10 02:04:39 +00002# Copyright 2014 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
6"""Test gsutil.py."""
7
Edward Lemur83aafc92019-11-25 23:25:05 +00008from __future__ import unicode_literals
hinoka@chromium.org7a790542014-12-10 02:04:39 +00009
Edward Lemur83aafc92019-11-25 23:25:05 +000010
hinoka@chromium.org7a790542014-12-10 02:04:39 +000011import base64
hinoka@chromium.org5e879a42015-01-24 00:55:46 +000012import hashlib
Edward Lemur83aafc92019-11-25 23:25:05 +000013import io
hinoka@chromium.org7a790542014-12-10 02:04:39 +000014import json
15import os
hinoka@chromium.org5e879a42015-01-24 00:55:46 +000016import shutil
17import subprocess
18import sys
19import tempfile
20import unittest
hinoka@chromium.org5e879a42015-01-24 00:55:46 +000021import zipfile
hinoka@chromium.org7a790542014-12-10 02:04:39 +000022
Edward Lemur83aafc92019-11-25 23:25:05 +000023try:
24 import urllib2 as urllib
25except ImportError: # For Py3 compatibility
26 import urllib.request as urllib
hinoka@chromium.org7a790542014-12-10 02:04:39 +000027
28# Add depot_tools to path
29THIS_DIR = os.path.dirname(os.path.abspath(__file__))
30DEPOT_TOOLS_DIR = os.path.dirname(THIS_DIR)
31sys.path.append(DEPOT_TOOLS_DIR)
32
33import gsutil
34
35
36class TestError(Exception):
37 pass
38
39
hinoka@chromium.org7a790542014-12-10 02:04:39 +000040class FakeCall(object):
41 def __init__(self):
42 self.expectations = []
43
44 def add_expectation(self, *args, **kwargs):
45 returns = kwargs.pop('_returns', None)
46 self.expectations.append((args, kwargs, returns))
47
48 def __call__(self, *args, **kwargs):
49 if not self.expectations:
50 raise TestError('Got unexpected\n%s\n%s' % (args, kwargs))
51 exp_args, exp_kwargs, exp_returns = self.expectations.pop(0)
52 if args != exp_args or kwargs != exp_kwargs:
53 message = 'Expected:\n args: %s\n kwargs: %s\n' % (exp_args, exp_kwargs)
54 message += 'Got:\n args: %s\n kwargs: %s\n' % (args, kwargs)
55 raise TestError(message)
hinoka@chromium.org7a790542014-12-10 02:04:39 +000056 return exp_returns
57
58
59class GsutilUnitTests(unittest.TestCase):
60 def setUp(self):
61 self.fake = FakeCall()
62 self.tempdir = tempfile.mkdtemp()
Edward Lemur83aafc92019-11-25 23:25:05 +000063 self.old_urlopen = getattr(urllib, 'urlopen')
hinoka@chromium.org5e879a42015-01-24 00:55:46 +000064 self.old_call = getattr(subprocess, 'call')
Edward Lemur83aafc92019-11-25 23:25:05 +000065 setattr(urllib, 'urlopen', self.fake)
hinoka@chromium.org5e879a42015-01-24 00:55:46 +000066 setattr(subprocess, 'call', self.fake)
hinoka@chromium.org7a790542014-12-10 02:04:39 +000067
68 def tearDown(self):
69 self.assertEqual(self.fake.expectations, [])
70 shutil.rmtree(self.tempdir)
Edward Lemur83aafc92019-11-25 23:25:05 +000071 setattr(urllib, 'urlopen', self.old_urlopen)
hinoka@chromium.org5e879a42015-01-24 00:55:46 +000072 setattr(subprocess, 'call', self.old_call)
hinoka@chromium.org7a790542014-12-10 02:04:39 +000073
74 def test_download_gsutil(self):
75 version = '4.2'
76 filename = 'gsutil_%s.zip' % version
77 full_filename = os.path.join(self.tempdir, filename)
Edward Lemur83aafc92019-11-25 23:25:05 +000078 fake_file = b'This is gsutil.zip'
79 fake_file2 = b'This is other gsutil.zip'
hinoka@chromium.org7a790542014-12-10 02:04:39 +000080 url = '%s%s' % (gsutil.GSUTIL_URL, filename)
Edward Lemur83aafc92019-11-25 23:25:05 +000081 self.fake.add_expectation(url, _returns=io.BytesIO(fake_file))
hinoka@chromium.org7a790542014-12-10 02:04:39 +000082
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +000083 self.assertEqual(
hinoka@chromium.org7a790542014-12-10 02:04:39 +000084 gsutil.download_gsutil(version, self.tempdir), full_filename)
Edward Lemur83aafc92019-11-25 23:25:05 +000085 with open(full_filename, 'rb') as f:
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +000086 self.assertEqual(fake_file, f.read())
hinoka@chromium.org7a790542014-12-10 02:04:39 +000087
88 metadata_url = gsutil.API_URL + filename
89 md5_calc = hashlib.md5()
90 md5_calc.update(fake_file)
Edward Lemur83aafc92019-11-25 23:25:05 +000091 b64_md5 = base64.b64encode(md5_calc.hexdigest().encode('utf-8'))
92 self.fake.add_expectation(
93 metadata_url,
94 _returns=io.BytesIO(
95 json.dumps({'md5Hash': b64_md5.decode('utf-8')}).encode('utf-8')))
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +000096 self.assertEqual(
hinoka@chromium.org7a790542014-12-10 02:04:39 +000097 gsutil.download_gsutil(version, self.tempdir), full_filename)
Edward Lemur83aafc92019-11-25 23:25:05 +000098 with open(full_filename, 'rb') as f:
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +000099 self.assertEqual(fake_file, f.read())
100 self.assertEqual(self.fake.expectations, [])
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000101
Edward Lemur83aafc92019-11-25 23:25:05 +0000102 self.fake.add_expectation(
103 metadata_url,
104 _returns=io.BytesIO(
105 json.dumps({
106 'md5Hash': base64.b64encode(b'aaaaaaa').decode('utf-8') # Bad MD5
107 }).encode('utf-8')))
108 self.fake.add_expectation(url, _returns=io.BytesIO(fake_file2))
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +0000109 self.assertEqual(
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000110 gsutil.download_gsutil(version, self.tempdir), full_filename)
Edward Lemur83aafc92019-11-25 23:25:05 +0000111 with open(full_filename, 'rb') as f:
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +0000112 self.assertEqual(fake_file2, f.read())
113 self.assertEqual(self.fake.expectations, [])
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000114
115 def test_ensure_gsutil_full(self):
116 version = '4.2'
117 gsutil_dir = os.path.join(self.tempdir, 'gsutil_%s' % version, 'gsutil')
118 gsutil_bin = os.path.join(gsutil_dir, 'gsutil')
Ryan Tseng83fd81f2017-10-23 11:13:48 -0700119 gsutil_flag = os.path.join(gsutil_dir, 'install.flag')
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000120 os.makedirs(gsutil_dir)
121
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000122 zip_filename = 'gsutil_%s.zip' % version
123 url = '%s%s' % (gsutil.GSUTIL_URL, zip_filename)
124 _, tempzip = tempfile.mkstemp()
125 fake_gsutil = 'Fake gsutil'
126 with zipfile.ZipFile(tempzip, 'w') as zf:
127 zf.writestr('gsutil/gsutil', fake_gsutil)
128 with open(tempzip, 'rb') as f:
Edward Lemur83aafc92019-11-25 23:25:05 +0000129 self.fake.add_expectation(url, _returns=io.BytesIO(f.read()))
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000130
Ryan Tseng83fd81f2017-10-23 11:13:48 -0700131 # This should write the gsutil_bin with 'Fake gsutil'
132 gsutil.ensure_gsutil(version, self.tempdir, False)
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000133 self.assertTrue(os.path.exists(gsutil_bin))
134 with open(gsutil_bin, 'r') as f:
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +0000135 self.assertEqual(f.read(), fake_gsutil)
Ryan Tseng83fd81f2017-10-23 11:13:48 -0700136 self.assertTrue(os.path.exists(gsutil_flag))
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +0000137 self.assertEqual(self.fake.expectations, [])
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000138
139 def test_ensure_gsutil_short(self):
140 version = '4.2'
141 gsutil_dir = os.path.join(self.tempdir, 'gsutil_%s' % version, 'gsutil')
142 gsutil_bin = os.path.join(gsutil_dir, 'gsutil')
Ryan Tseng83fd81f2017-10-23 11:13:48 -0700143 gsutil_flag = os.path.join(gsutil_dir, 'install.flag')
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000144 os.makedirs(gsutil_dir)
145
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000146 with open(gsutil_bin, 'w') as f:
147 f.write('Foobar')
Ryan Tseng83fd81f2017-10-23 11:13:48 -0700148 with open(gsutil_flag, 'w') as f:
149 f.write('Barbaz')
Raphael Kubo da Costae9342a72019-10-14 17:49:39 +0000150 self.assertEqual(
dnj@chromium.org605d81d2015-09-18 22:33:53 +0000151 gsutil.ensure_gsutil(version, self.tempdir, False), gsutil_bin)
hinoka@chromium.org7a790542014-12-10 02:04:39 +0000152
153if __name__ == '__main__':
154 unittest.main()