Path: blob/develop/tests/unit/customizations/gamelift/test_uploadbuild.py
1569 views
# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12from argparse import Namespace13import contextlib14import os15import zipfile1617from botocore.session import get_session18from botocore.exceptions import ClientError1920from awscli.testutils import unittest, mock, FileCreator21from awscli.customizations.gamelift.uploadbuild import UploadBuildCommand22from awscli.customizations.gamelift.uploadbuild import zip_directory23from awscli.customizations.gamelift.uploadbuild import validate_directory24from awscli.compat import StringIO252627class TestGetGameSessionLogCommand(unittest.TestCase):28def setUp(self):29self.create_client_patch = mock.patch(30'botocore.session.Session.create_client')31self.mock_create_client = self.create_client_patch.start()32self.session = get_session()3334self.gamelift_client = mock.Mock()35self.s3_client = mock.Mock()36self.mock_create_client.side_effect = [37self.gamelift_client, self.s3_client38]3940self.file_creator = FileCreator()41self.upload_file_patch = mock.patch(42'awscli.customizations.gamelift.uploadbuild.S3Transfer.upload_file'43)44self.upload_file_mock = self.upload_file_patch.start()4546self.cmd = UploadBuildCommand(self.session)47self._setup_input_output()4849def tearDown(self):50self.create_client_patch.stop()51self.file_creator.remove_all()52self.upload_file_patch.stop()5354def _setup_input_output(self):55# Input values56self.region = 'us-west-2'57self.build_name = 'mybuild'58self.build_version = 'myversion'59self.build_root = self.file_creator.rootdir6061self.args = [62'--name', self.build_name, '--build-version', self.build_version,63'--build-root', self.build_root64]6566self.global_args = Namespace()67self.global_args.region = self.region68self.global_args.endpoint_url = None69self.global_args.verify_ssl = None7071# Output values72self.build_id = 'myid'73self.bucket = 'mybucket'74self.key = 'mykey'75self.access_key = 'myaccesskey'76self.secret_key = 'mysecretkey'77self.session_token = 'mytoken'7879self.gamelift_client.create_build.return_value = {80'Build': {81'BuildId': self.build_id82}83}8485self.gamelift_client.request_upload_credentials.return_value = {86'StorageLocation': {87'Bucket': self.bucket,88'Key': self.key89},90'UploadCredentials': {91'AccessKeyId': self.access_key,92'SecretAccessKey': self.secret_key,93'SessionToken': self.session_token94}95}9697def test_upload_build(self):98self.file_creator.create_file('tmpfile', 'Some contents')99self.cmd(self.args, self.global_args)100# Ensure the clients were instantiated correctly.101client_creation_args = self.mock_create_client.call_args_list102self.assertEqual(103client_creation_args,104[mock.call('gamelift', region_name=self.region,105endpoint_url=None, verify=None),106mock.call('s3', aws_access_key_id=self.access_key,107aws_secret_access_key=self.secret_key,108aws_session_token=self.session_token,109region_name=self.region,110verify=None)]111)112113# Ensure the GameLift client was called correctly.114self.gamelift_client.create_build.assert_called_once_with(115Name=self.build_name, Version=self.build_version)116117self.gamelift_client.request_upload_credentials.\118assert_called_once_with(BuildId=self.build_id)119120# Ensure the underlying S3 transfer call was correct.121self.upload_file_mock.assert_called_once_with(122mock.ANY, self.bucket, self.key, callback=mock.ANY)123124tempfile_path = self.upload_file_mock.call_args[0][0]125# Ensure the temporary zipfile is deleted at the end.126self.assertFalse(os.path.exists(tempfile_path))127128def test_upload_build_when_operating_system_is_provided(self):129operating_system = 'WINDOWS_2012'130self.file_creator.create_file('tmpfile', 'Some contents')131self.args = [132'--name', self.build_name, '--build-version', self.build_version,133'--build-root', self.build_root,134'--operating-system', operating_system135]136self.cmd(self.args, self.global_args)137138# Ensure the GameLift client was called correctly.139self.gamelift_client.create_build.assert_called_once_with(140Name=self.build_name, Version=self.build_version,141OperatingSystem=operating_system)142143def test_error_message_when_directory_is_empty(self):144with mock.patch('sys.stderr', StringIO()) as mock_stderr:145self.cmd(self.args, self.global_args)146self.assertEqual(147mock_stderr.getvalue(),148'Fail to upload %s. '149'The build root directory is empty or does not exist.\n'150% (self.build_root)151)152153def test_error_message_when_directory_is_not_provided(self):154self.args = [155'--name', self.build_name,156'--build-version', self.build_version,157'--build-root', ''158]159160with mock.patch('sys.stderr', StringIO()) as mock_stderr:161self.cmd(self.args, self.global_args)162self.assertEqual(163mock_stderr.getvalue(),164'Fail to upload %s. '165'The build root directory is empty or does not exist.\n' % ('')166)167168def test_error_message_when_directory_does_not_exist(self):169dir_not_exist = os.path.join(self.build_root, 'does_not_exist')170171self.args = [172'--name', self.build_name,173'--build-version', self.build_version,174'--build-root', dir_not_exist175]176177with mock.patch('sys.stderr', StringIO()) as mock_stderr:178self.cmd(self.args, self.global_args)179self.assertEqual(180mock_stderr.getvalue(),181'Fail to upload %s. '182'The build root directory is empty or does not exist.\n'183% (dir_not_exist)184)185186def test_temporary_file_does_exist_when_fails(self):187self.upload_file_mock.side_effect = ClientError(188{'Error': {'Code': 403, 'Message': 'No Access'}}, 'PutObject')189with self.assertRaises(ClientError):190self.file_creator.create_file('tmpfile', 'Some contents')191self.cmd(self.args, self.global_args)192tempfile_path = self.upload_file_mock.call_args[0][0]193# Make sure the temporary file is removed.194self.assertFalse(os.path.exists(tempfile_path))195196def test_upload_build_when_server_sdk_version_is_provided(self):197server_sdk_version = '4.0.2'198self.file_creator.create_file('tmpfile', 'Some contents')199self.args = [200'--name', self.build_name, '--build-version', self.build_version,201'--build-root', self.build_root,202'--server-sdk-version', server_sdk_version203]204self.cmd(self.args, self.global_args)205206# Ensure the GameLift client was called correctly.207self.gamelift_client.create_build.assert_called_once_with(208Name=self.build_name, Version=self.build_version,209ServerSdkVersion=server_sdk_version)210211212class TestZipDirectory(unittest.TestCase):213def setUp(self):214self.file_creator = FileCreator()215self.zip_file = self.file_creator.create_file('build.zip', '')216self._dir_root = 'mybuild'217218def tearDown(self):219self.file_creator.remove_all()220221@property222def dir_root(self):223return self.file_creator.full_path(self._dir_root)224225def add_to_directory(self, filename):226self.file_creator.create_file(227os.path.join(self._dir_root, filename), 'Some contents')228229def assert_contents_of_zip_file(self, filenames):230zip_file_object = zipfile.ZipFile(231self.zip_file, 'r', zipfile.ZIP_DEFLATED)232with contextlib.closing(zip_file_object) as zf:233ref_zipfiles = []234zipfile_contents = zf.namelist()235for ref_zipfile in zipfile_contents:236if os.sep == '\\':237# Internally namelist() represent directories with238# forward slashes so we need to account for that if239# the separator is a backslash depending on the operating240# system.241ref_zipfile = ref_zipfile.replace('/', '\\')242ref_zipfiles.append(ref_zipfile)243self.assertEqual(sorted(ref_zipfiles), filenames)244245def test_single_file(self):246self.add_to_directory('foo')247zip_directory(self.zip_file, self.dir_root)248self.assert_contents_of_zip_file(['foo'])249250def test_multiple_files(self):251self.add_to_directory('foo')252self.add_to_directory('bar')253zip_directory(self.zip_file, self.dir_root)254self.assert_contents_of_zip_file(['bar', 'foo'])255256def test_nested_file(self):257filename = os.path.join('mydir', 'foo')258self.add_to_directory(filename)259zip_directory(self.zip_file, self.dir_root)260self.assert_contents_of_zip_file([filename])261262263class TestValidateDirectory(unittest.TestCase):264def setUp(self):265self.file_creator = FileCreator()266self.dir_root = self.file_creator.rootdir267268def tearDown(self):269self.file_creator.remove_all()270271def test_directory_contains_single_file(self):272self.file_creator.create_file('foo', '')273self.assertTrue(validate_directory(self.dir_root))274275def test_directory_contains_file_and_empty_directory(self):276dirname = os.path.join(self.dir_root, 'foo')277os.makedirs(dirname)278self.file_creator.create_file('bar', '')279self.assertTrue(validate_directory(self.dir_root))280281def test_nested_file(self):282self.file_creator.create_file('mydir/bar', '')283self.assertTrue(validate_directory(self.dir_root))284285def test_empty_directory(self):286self.assertFalse(validate_directory(self.dir_root))287288def test_nonexistent_directory(self):289dir_not_exist = os.path.join(self.dir_root, 'does_not_exist')290self.assertFalse(validate_directory(dir_not_exist))291292def test_nonprovided_directory(self):293self.assertFalse(validate_directory(''))294295def test_empty_nested_directory(self):296dirname = os.path.join(self.dir_root, 'foo')297os.makedirs(dirname)298self.assertFalse(validate_directory(self.dir_root))299300301