|
@@ -50,6 +50,13 @@ class FakeCall(object):
|
|
|
return exp_returns
|
|
|
|
|
|
|
|
|
+class MockResponse(io.BytesIO):
|
|
|
+
|
|
|
+ def info(self):
|
|
|
+ # urlretrieve expects info() to return a dictionary.
|
|
|
+ return {}
|
|
|
+
|
|
|
+
|
|
|
class GsutilUnitTests(unittest.TestCase):
|
|
|
def setUp(self):
|
|
|
self.fake = FakeCall()
|
|
@@ -65,44 +72,53 @@ class GsutilUnitTests(unittest.TestCase):
|
|
|
setattr(urllib.request, 'urlopen', self.old_urlopen)
|
|
|
setattr(subprocess, 'call', self.old_call)
|
|
|
|
|
|
+ def add_md5_expectation(self, url, data):
|
|
|
+ md5_calc = hashlib.md5()
|
|
|
+ md5_calc.update(data)
|
|
|
+ b64_md5 = base64.b64encode(md5_calc.digest()).decode('utf-8')
|
|
|
+ response_data = json.dumps({'md5Hash': b64_md5}).encode('utf-8')
|
|
|
+ self.fake.add_expectation(url, _returns=MockResponse(response_data))
|
|
|
+
|
|
|
+ def add_file_expectation(self, url, data):
|
|
|
+ self.fake.add_expectation(url, None, _returns=MockResponse(data))
|
|
|
+
|
|
|
def test_download_gsutil(self):
|
|
|
version = gsutil.VERSION
|
|
|
filename = 'gsutil_%s.zip' % version
|
|
|
full_filename = os.path.join(self.tempdir, filename)
|
|
|
fake_file = b'This is gsutil.zip'
|
|
|
fake_file2 = b'This is other gsutil.zip'
|
|
|
- url = '%s%s' % (gsutil.GSUTIL_URL, filename)
|
|
|
- self.fake.add_expectation(url, _returns=io.BytesIO(fake_file))
|
|
|
+ metadata_url = gsutil.API_URL + filename
|
|
|
+ url = gsutil.GSUTIL_URL + filename
|
|
|
|
|
|
+ # The md5 is valid, so download_gsutil should download the file.
|
|
|
+ self.add_md5_expectation(metadata_url, fake_file)
|
|
|
+ self.add_file_expectation(url, fake_file)
|
|
|
self.assertEqual(gsutil.download_gsutil(version, self.tempdir),
|
|
|
full_filename)
|
|
|
with open(full_filename, 'rb') as f:
|
|
|
self.assertEqual(fake_file, f.read())
|
|
|
+ self.assertEqual(self.fake.expectations, [])
|
|
|
|
|
|
- metadata_url = gsutil.API_URL + filename
|
|
|
- md5_calc = hashlib.md5()
|
|
|
- md5_calc.update(fake_file)
|
|
|
- b64_md5 = base64.b64encode(md5_calc.hexdigest().encode('utf-8'))
|
|
|
- self.fake.add_expectation(metadata_url,
|
|
|
- _returns=io.BytesIO(
|
|
|
- json.dumps({
|
|
|
- 'md5Hash':
|
|
|
- b64_md5.decode('utf-8')
|
|
|
- }).encode('utf-8')))
|
|
|
+ # The md5 is valid, so download_gsutil should use the existing file.
|
|
|
+ self.add_md5_expectation(metadata_url, fake_file)
|
|
|
self.assertEqual(gsutil.download_gsutil(version, self.tempdir),
|
|
|
full_filename)
|
|
|
with open(full_filename, 'rb') as f:
|
|
|
self.assertEqual(fake_file, f.read())
|
|
|
self.assertEqual(self.fake.expectations, [])
|
|
|
|
|
|
- self.fake.add_expectation(
|
|
|
- metadata_url,
|
|
|
- _returns=io.BytesIO(
|
|
|
- json.dumps({
|
|
|
- 'md5Hash':
|
|
|
- base64.b64encode(b'aaaaaaa').decode('utf-8') # Bad MD5
|
|
|
- }).encode('utf-8')))
|
|
|
- self.fake.add_expectation(url, _returns=io.BytesIO(fake_file2))
|
|
|
+ # The md5 is invalid for a new file, so download_gsutil should raise an
|
|
|
+ # error.
|
|
|
+ self.add_md5_expectation(metadata_url, b'aaaaaaa')
|
|
|
+ self.add_file_expectation(url, fake_file2)
|
|
|
+ self.assertRaises(gsutil.InvalidGsutilError, gsutil.download_gsutil,
|
|
|
+ version, self.tempdir)
|
|
|
+ self.assertEqual(self.fake.expectations, [])
|
|
|
+
|
|
|
+ # The md5 is valid and the new file is already downloaded, so it should
|
|
|
+ # be used without downloading again.
|
|
|
+ self.add_md5_expectation(metadata_url, fake_file2)
|
|
|
self.assertEqual(gsutil.download_gsutil(version, self.tempdir),
|
|
|
full_filename)
|
|
|
with open(full_filename, 'rb') as f:
|
|
@@ -117,13 +133,16 @@ class GsutilUnitTests(unittest.TestCase):
|
|
|
os.makedirs(gsutil_dir)
|
|
|
|
|
|
zip_filename = 'gsutil_%s.zip' % version
|
|
|
- url = '%s%s' % (gsutil.GSUTIL_URL, zip_filename)
|
|
|
+ metadata_url = gsutil.API_URL + zip_filename
|
|
|
+ url = gsutil.GSUTIL_URL + zip_filename
|
|
|
_, tempzip = tempfile.mkstemp()
|
|
|
fake_gsutil = 'Fake gsutil'
|
|
|
with zipfile.ZipFile(tempzip, 'w') as zf:
|
|
|
zf.writestr('gsutil/gsutil', fake_gsutil)
|
|
|
with open(tempzip, 'rb') as f:
|
|
|
- self.fake.add_expectation(url, _returns=io.BytesIO(f.read()))
|
|
|
+ fake_file = f.read()
|
|
|
+ self.add_md5_expectation(metadata_url, fake_file)
|
|
|
+ self.add_file_expectation(url, fake_file)
|
|
|
|
|
|
# This should write the gsutil_bin with 'Fake gsutil'
|
|
|
gsutil.ensure_gsutil(version, self.tempdir, False)
|