Merge branch 'development' of https://github.com/o3de/o3de into jckand/LinuxCrashTest

Signed-off-by: jckand-amzn <82226555+jckand-amzn@users.noreply.github.com>
This commit is contained in:
jckand-amzn
2021-12-06 09:11:02 -06:00
46 changed files with 2601 additions and 3666 deletions
@@ -293,61 +293,75 @@ def delete(file_list, del_files, del_dirs):
return True
def create_backup(source, backup_dir):
def create_backup(source, backup_dir, backup_name=None):
"""
Creates a backup of a single source file by creating a copy of it with the same name + '.bak' in backup_dir
e.g.: foo.txt is stored as backup_dir/foo.txt.bak
If backup_name is provided, it will create a copy of the source file named "backup_name + .bak" instead.
:param source: Full path to file to backup
:param backup_dir: Path to the directory to store backup.
:param backup_name: [Optional] Name of the backed up file to use instead or the source name.
"""
if not backup_dir or not os.path.isdir(backup_dir):
logger.error(f'Cannot create backup due to invalid backup directory {backup_dir}')
return
return False
if not os.path.exists(source):
logger.warning(f'Source file {source} does not exist, aborting backup creation.')
return
return False
source_filename = os.path.basename(source)
dest = os.path.join(backup_dir, f'{source_filename}.bak')
dest = None
if backup_name is None:
source_filename = os.path.basename(source)
dest = os.path.join(backup_dir, f'{source_filename}.bak')
else:
dest = os.path.join(backup_dir, f'{backup_name}.bak')
logger.info(f'Saving backup of {source} in {dest}')
if os.path.exists(dest):
logger.warning(f'Backup file already exists at {dest}, it will be overwritten.')
try:
shutil.copy(source, dest)
shutil.copy2(source, dest)
except Exception: # intentionally broad
logger.warning('Could not create backup, exception occurred while copying.', exc_info=True)
return False
return True
def restore_backup(original_file, backup_dir):
def restore_backup(original_file, backup_dir, backup_name=None):
"""
Restores a backup file to its original location. Works with a single file only.
:param original_file: Full path to file to overwrite.
:param backup_dir: Path to the directory storing the backup.
:param backup_name: [Optional] Provide if the backup file name is different from source. eg backup file = myFile_1.txt.bak original file = myfile.txt
"""
if not backup_dir or not os.path.isdir(backup_dir):
logger.error(f'Cannot restore backup due to invalid or nonexistent directory {backup_dir}.')
return
return False
source_filename = os.path.basename(original_file)
backup = os.path.join(backup_dir, f'{source_filename}.bak')
backup = None
if backup_name is None:
source_filename = os.path.basename(original_file)
backup = os.path.join(backup_dir, f'{source_filename}.bak')
else:
backup = os.path.join(backup_dir, f'{backup_name}.bak')
if not os.path.exists(backup):
logger.warning(f'Backup file {backup} does not exist, aborting backup restoration.')
return
return False
logger.info(f'Restoring backup of {original_file} from {backup}')
try:
shutil.copy(backup, original_file)
shutil.copy2(backup, original_file)
except Exception: # intentionally broad
logger.warning('Could not restore backup, exception occurred while copying.', exc_info=True)
return False
return True
def delete_oldest(path_glob, keep_num, del_files=True, del_dirs=False):
""" Delete oldest builds, keeping a specific number """
@@ -163,9 +163,23 @@ class AndroidLauncher(Launcher):
return True
def setup(self):
def setup(self, backupFiles=True, launch_ap=True, configure_settings=True):
"""
Perform setup of this launcher, must be called before launching.
Subclasses should call its parent's setup() before calling its own code, unless it changes configuration files
:param backupFiles: Bool to backup setup files
:param launch_ap: Bool to launch the asset processor
:param configure_settings: Bool to update settings caches
:return: None
"""
# Backup
self.backup_settings()
if backupFiles:
self.backup_settings()
# None reverts to function default
if launch_ap is None:
launch_ap = True
# Enable Android capabilities and verify environment is setup before continuing.
self._is_valid_android_environment()
@@ -174,7 +188,7 @@ class AndroidLauncher(Launcher):
# Modify and re-configure
self.configure_settings()
self.workspace.shader_compiler.start()
super(AndroidLauncher, self).setup()
super(AndroidLauncher, self).setup(backupFiles, launch_ap, configure_settings)
def teardown(self):
ly_test_tools.mobile.android.undo_tcp_port_changes(self._device_id)
@@ -75,6 +75,8 @@ class Launcher(object):
~/ly_test_tools/devices.ini (a.k.a. %USERPROFILE%/ly_test_tools/devices.ini)
:param backupFiles: Bool to backup setup files
:param launch_ap: Bool to launch the asset processor
:param configure_settings: Bool to update settings caches
:return: None
"""
# Remove existing logs and dmp files before launching for self.save_project_log_files()
@@ -52,7 +52,7 @@ class LinuxLauncher(Launcher):
if backupFiles:
self.backup_settings()
# Base setup defaults to None
# None reverts to function default
if launch_ap is None:
launch_ap = True
@@ -162,7 +162,7 @@ class LinuxLauncher(Launcher):
def configure_settings(self):
"""
Configures system level settings and syncs the launcher to the targeted console IP.
Configures system level settings
:return: None
"""
@@ -170,7 +170,6 @@ class LinuxLauncher(Launcher):
host_ip = '127.0.0.1'
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/project_path={self.workspace.paths.project()}"')
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/remote_ip={host_ip}"')
self.args.append('--regset="/Amazon/AzCore/Bootstrap/wait_for_connect=1"')
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/allowed_list={host_ip}"')
self.workspace.settings.modify_platform_setting("r_ShaderCompilerServer", host_ip)
@@ -179,20 +178,25 @@ class LinuxLauncher(Launcher):
class DedicatedLinuxLauncher(LinuxLauncher):
def setup(self, backupFiles=True, launch_ap=False):
def setup(self, backupFiles=True, launch_ap=False, configure_settings=True):
"""
Perform setup of this launcher, must be called before launching.
Subclasses should call its parent's setup() before calling its own code, unless it changes configuration files
:param backupFiles: Bool to backup setup files
:param lauch_ap: Bool to lauch the asset processor
:param launch_ap: Bool to launch the asset processor
:param configure_settings: Bool to update settings caches
:return: None
"""
# Base setup defaults to None
# Backup
if backupFiles:
self.backup_settings()
# None reverts to function default
if launch_ap is None:
launch_ap = False
super(DedicatedLinuxLauncher, self).setup(backupFiles, launch_ap)
super(DedicatedLinuxLauncher, self).setup(backupFiles, launch_ap, configure_settings)
def binary_path(self):
"""
@@ -44,21 +44,22 @@ class WinLauncher(Launcher):
Subclasses should call its parent's setup() before calling its own code, unless it changes configuration files
:param backupFiles: Bool to backup setup files
:param lauch_ap: Bool to lauch the asset processor
:param launch_ap: Bool to lauch the asset processor
:param configure_settings: Bool to update settings caches
:return: None
"""
# Backup
if backupFiles:
self.backup_settings()
# Base setup defaults to None
# None reverts to function default
if launch_ap is None:
launch_ap = True
# Modify and re-configure
if configure_settings:
self.configure_settings()
super(WinLauncher, self).setup(backupFiles, launch_ap)
super(WinLauncher, self).setup(backupFiles, launch_ap, configure_settings)
def launch(self):
"""
@@ -161,7 +162,7 @@ class WinLauncher(Launcher):
def configure_settings(self):
"""
Configures system level settings and syncs the launcher to the targeted console IP.
Configures system level settings
:return: None
"""
@@ -169,7 +170,6 @@ class WinLauncher(Launcher):
host_ip = '127.0.0.1'
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/project_path={self.workspace.paths.project()}"')
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/remote_ip={host_ip}"')
self.args.append('--regset="/Amazon/AzCore/Bootstrap/wait_for_connect=1"')
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/allowed_list={host_ip}"')
self.workspace.settings.modify_platform_setting("log_RemoteConsoleAllowedAddresses", host_ip)
@@ -177,20 +177,25 @@ class WinLauncher(Launcher):
class DedicatedWinLauncher(WinLauncher):
def setup(self, backupFiles=True, launch_ap=False):
def setup(self, backupFiles=True, launch_ap=False, configure_settings=True):
"""
Perform setup of this launcher, must be called before launching.
Subclasses should call its parent's setup() before calling its own code, unless it changes configuration files
:param backupFiles: Bool to backup setup files
:param lauch_ap: Bool to lauch the asset processor
:param launch_ap: Bool to launch the asset processor
:param configure_settings: Bool to update settings caches
:return: None
"""
# Base setup defaults to None
# Backup
if backupFiles:
self.backup_settings()
# None reverts to function default
if launch_ap is None:
launch_ap = False
super(DedicatedWinLauncher, self).setup(backupFiles, launch_ap)
super(DedicatedWinLauncher, self).setup(backupFiles, launch_ap, configure_settings)
def binary_path(self):
"""
@@ -751,7 +751,7 @@ class TestFileBackup(unittest.TestCase):
self._dummy_file = 'dummy.txt'
self._dummy_backup_file = os.path.join(self._dummy_dir, '{}.bak'.format(self._dummy_file))
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_BackupSettings_SourceExists_BackupCreated(self, mock_path_isdir, mock_backup_exists, mock_copy):
@@ -763,7 +763,7 @@ class TestFileBackup(unittest.TestCase):
mock_copy.assert_called_with(self._dummy_file, self._dummy_backup_file)
@mock.patch('ly_test_tools.environment.file_system.logger.warning')
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_BackupSettings_BackupExists_WarningLogged(self, mock_path_isdir, mock_backup_exists, mock_copy, mock_logger_warning):
@@ -776,7 +776,7 @@ class TestFileBackup(unittest.TestCase):
mock_logger_warning.assert_called_once()
@mock.patch('ly_test_tools.environment.file_system.logger.warning')
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_BackupSettings_SourceNotExists_WarningLogged(self, mock_path_isdir, mock_backup_exists, mock_copy, mock_logger_warning):
@@ -789,7 +789,7 @@ class TestFileBackup(unittest.TestCase):
mock_logger_warning.assert_called_once()
@mock.patch('ly_test_tools.environment.file_system.logger.warning')
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_BackupSettings_CannotCopy_WarningLogged(self, mock_path_isdir, mock_backup_exists, mock_copy, mock_logger_warning):
@@ -821,7 +821,7 @@ class TestFileBackupRestore(unittest.TestCase):
self._dummy_file = 'dummy.txt'
self._dummy_backup_file = os.path.join(self._dummy_dir, '{}.bak'.format(self._dummy_file))
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_RestoreSettings_BackupRestore_Success(self, mock_path_isdir, mock_exists, mock_copy):
@@ -832,7 +832,7 @@ class TestFileBackupRestore(unittest.TestCase):
mock_copy.assert_called_with(self._dummy_backup_file, self._dummy_file)
@mock.patch('ly_test_tools.environment.file_system.logger.warning')
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_RestoreSettings_CannotCopy_WarningLogged(self, mock_path_isdir, mock_exists, mock_copy, mock_logger_warning):
@@ -846,7 +846,7 @@ class TestFileBackupRestore(unittest.TestCase):
mock_logger_warning.assert_called_once()
@mock.patch('ly_test_tools.environment.file_system.logger.warning')
@mock.patch('shutil.copy')
@mock.patch('shutil.copy2')
@mock.patch('os.path.exists')
@mock.patch('os.path.isdir')
def test_RestoreSettings_BackupNotExists_WarningLogged(self, mock_path_isdir, mock_exists, mock_copy, mock_logger_warning):