rename to tmp name
This commit is contained in:
@@ -0,0 +1,350 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
"""
|
||||
|
||||
# Imports
|
||||
import os
|
||||
import shutil
|
||||
import json
|
||||
import logging
|
||||
import ly_test_tools.environment.file_system as fs
|
||||
|
||||
|
||||
class FileManagement:
|
||||
"""
|
||||
File Management static class: Handles file backup and restoration.
|
||||
Organizes backing up files into a single directory and
|
||||
mapping the back up files to their original files.
|
||||
|
||||
Features accessible via the exposed decorator functions.
|
||||
"""
|
||||
|
||||
# Static variables
|
||||
MAX_BACKUPS = 10000 # Arbitrary number to cap same-file-name name generating
|
||||
backup_folder_name = ".backup"
|
||||
backup_folder_path = os.path.join(os.path.split(__file__)[0], backup_folder_name) # CWD plus backup folder name
|
||||
file_map_name = "_filebackup_map.json" # JSON file to store original to back up file mappings
|
||||
|
||||
@staticmethod
|
||||
def _load_file_map():
|
||||
# type: () -> {str: str}
|
||||
"""
|
||||
Loads the FileManagement's json file map.
|
||||
The returned dictionary has key: value sets such that:
|
||||
keys: full path to an original file currently being backed up
|
||||
values: name of the original file's backup file. Uses a numbering system for
|
||||
storing multiple file names that are identical but located in different directories.
|
||||
If there is no current json file or the file cannot be parsed, an empty dictionary is returned.
|
||||
:return: Dictionary to map original file's to their back up file names.
|
||||
"""
|
||||
json_file_path = os.path.join(FileManagement.backup_folder_path, FileManagement.file_map_name)
|
||||
if os.path.exists(json_file_path):
|
||||
try:
|
||||
with open(json_file_path, "r") as f:
|
||||
return json.load(f)
|
||||
except ValueError:
|
||||
logging.info("Decoding JSON file {} failed. Empty dictionary used".format(json_file_path))
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
def _save_file_map(file_map):
|
||||
# type: ({str: str}) -> None
|
||||
"""
|
||||
Saves the [file_map] dictionary as a json file.
|
||||
If [file_map] is empty, deletes the json file.
|
||||
:param file_map: A dictionary mapping original file paths to their back up file names.
|
||||
:return: None
|
||||
"""
|
||||
file_path = os.path.join(FileManagement.backup_folder_path, FileManagement.file_map_name)
|
||||
if os.path.exists(file_path):
|
||||
fs.unlock_file(file_path)
|
||||
if len(file_map) > 0:
|
||||
with open(file_path, "w") as f:
|
||||
json.dump(file_map, f)
|
||||
fs.lock_file(file_path)
|
||||
else:
|
||||
fs.delete([file_path], True, False)
|
||||
|
||||
@staticmethod
|
||||
def _next_available_name(file_name, file_map):
|
||||
# type: (str, {str: str}) -> str or None
|
||||
"""
|
||||
Generates the next available backup file name using a FILE_NAME_x.ext naming convention
|
||||
where x is a number. Returns None if we've maxed out the numbering system.
|
||||
:param file_name: The base file to generate a back up file name for.
|
||||
:param file_map: The file_map for the FileManagement system
|
||||
:return: str
|
||||
"""
|
||||
suffix, extension = file_name.split(".", 1)
|
||||
for i in range(FileManagement.MAX_BACKUPS):
|
||||
potential_name = suffix + "_" + str(i) + "." + extension
|
||||
if potential_name not in file_map.values():
|
||||
return potential_name
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _backup_file(file_name, file_path):
|
||||
# type: (str, str) -> None
|
||||
"""
|
||||
Backs up the [file_name] located at [file_path] into the FileManagement's backup folder.
|
||||
Leaves the backup file locked from writing privileges.
|
||||
:param file_name: The file's name that will be backed up
|
||||
:param file_path: The path to the file to back up
|
||||
:return: None
|
||||
"""
|
||||
file_map = FileManagement._load_file_map()
|
||||
backup_path = FileManagement.backup_folder_path
|
||||
backup_file_name = "{}.bak".format(file_name)
|
||||
backup_file = os.path.join(backup_path, backup_file_name)
|
||||
# If backup directory DNE, make one
|
||||
if not os.path.exists(backup_path):
|
||||
os.mkdir(backup_path)
|
||||
# If "traditional" backup file exists, delete it (myFile.txt.bak)
|
||||
if os.path.exists(backup_file):
|
||||
fs.delete([backup_file], True, False)
|
||||
# Find my next storage name (myFile_1.txt.bak)
|
||||
backup_storage_file_name = FileManagement._next_available_name(backup_file_name, file_map)
|
||||
if backup_storage_file_name is None:
|
||||
# If _next_available_name returns None, we have backed up MAX_BACKUPS of files name [file_name]
|
||||
raise Exception(
|
||||
"FileManagement class ran out of backups per name. Max: {}".format(FileManagement.MAX_BACKUPS)
|
||||
)
|
||||
backup_storage_file = os.path.join(backup_path, backup_storage_file_name)
|
||||
if os.path.exists(backup_storage_file):
|
||||
# This file should not exists, but if it does it's about to get clobbered!
|
||||
fs.unlock_file(backup_storage_file)
|
||||
# Create "traditional" backup file (myFile.txt.bak)
|
||||
fs.create_backup(os.path.join(file_path, file_name), backup_path)
|
||||
# Copy "traditional" backup file into storage backup (myFile_1.txt.bak)
|
||||
FileManagement._copy_file(backup_file_name, backup_path, backup_storage_file_name, backup_path)
|
||||
fs.lock_file(backup_storage_file)
|
||||
# Delete "traditional" back up file
|
||||
fs.unlock_file(backup_file)
|
||||
fs.delete([backup_file], True, False)
|
||||
# Update file map with new file
|
||||
file_map[os.path.join(file_path, file_name)] = backup_storage_file_name
|
||||
FileManagement._save_file_map(file_map)
|
||||
# Unlock original file to get it ready to be edited by the test
|
||||
fs.unlock_file(os.path.join(file_path, file_name))
|
||||
|
||||
@staticmethod
|
||||
def _restore_file(file_name, file_path):
|
||||
# type: (str, str) -> None
|
||||
"""
|
||||
Restores the [file_name] located at [file_path] which is backed up in FileManagement's backup folder.
|
||||
Locks [file_name] from writing privileges when done restoring.
|
||||
:param file_name: The Original file that was backed up, and now restored
|
||||
:param file_path: The location of the original file that was backed up
|
||||
:return: None
|
||||
"""
|
||||
file_map = FileManagement._load_file_map()
|
||||
backup_path = FileManagement.backup_folder_path
|
||||
src_file = os.path.join(file_path, file_name)
|
||||
if src_file in file_map:
|
||||
backup_file = os.path.join(backup_path, file_map[src_file])
|
||||
if os.path.exists(backup_file):
|
||||
fs.unlock_file(backup_file)
|
||||
fs.unlock_file(src_file)
|
||||
# Make temporary copy of backed up file to restore from
|
||||
temp_file = "{}.bak".format(file_name)
|
||||
FileManagement._copy_file(file_map[src_file], backup_path, temp_file, backup_path)
|
||||
fs.restore_backup(src_file, backup_path)
|
||||
fs.lock_file(src_file)
|
||||
# Delete backup file
|
||||
fs.delete([os.path.join(backup_path, temp_file)], True, False)
|
||||
fs.delete([backup_file], True, False)
|
||||
# Remove from file map
|
||||
del file_map[src_file]
|
||||
FileManagement._save_file_map(file_map)
|
||||
if not os.listdir(backup_path):
|
||||
# Delete backup folder if it's empty now
|
||||
os.rmdir(backup_path)
|
||||
|
||||
@staticmethod
|
||||
def _find_files(file_names, root_dir, search_subdirs=False):
|
||||
# type: ([str], str, bool) -> {str:str}
|
||||
"""
|
||||
Searches the [root_dir] directory tree for each of the file names in [file_names]. Returns a dictionary
|
||||
where keys = the entries in file_names, and their values are the paths they were found at.
|
||||
Raises a runtime warning if not exactly one copy of each file is found.
|
||||
:param file_names: A list of file_names to look for
|
||||
:param root_dir: The root directory to begin the search
|
||||
collect all file paths matching that file_name
|
||||
:param search_subdirs: Optional boolean flag for searching sub-directories of [parent_path]
|
||||
:return: A dictionary where keys are file names, and values are the file's path.
|
||||
"""
|
||||
file_list = {}
|
||||
found_count = 0
|
||||
for file_name in file_names:
|
||||
file_list[file_name] = None
|
||||
if search_subdirs:
|
||||
# Search parent path for all file name arguments
|
||||
for dir_path, _, dir_files in os.walk(root_dir):
|
||||
for dir_file in dir_files:
|
||||
if dir_file in file_list.keys():
|
||||
if file_list[dir_file] is None:
|
||||
file_list[dir_file] = dir_path
|
||||
found_count += 1
|
||||
else:
|
||||
# Found multiple files with same name. Raise warning.
|
||||
raise RuntimeWarning("Found multiple files with the name {}.".format(dir_file))
|
||||
else:
|
||||
for dir_file in os.listdir(root_dir):
|
||||
if os.path.isfile(os.path.join(root_dir, dir_file)) and dir_file in file_names:
|
||||
file_list[dir_file] = root_dir
|
||||
not_found = [file_name for file_name in file_names if file_list[file_name] is None]
|
||||
if not_found:
|
||||
raise RuntimeWarning("Could not find the following files: {}".format(not_found))
|
||||
|
||||
return file_list
|
||||
|
||||
@staticmethod
|
||||
def _copy_file(src_file, src_path, target_file, target_path):
|
||||
# type: (str, str, str, str) -> None
|
||||
"""
|
||||
Copies the [src_file] at located in [src_path] to the [target_file] located at [target_path].
|
||||
Leaves the [target_file] unlocked for reading and writing privileges
|
||||
:param src_file: The source file to copy (file name)
|
||||
:param src_path: The source file's path
|
||||
:param target_file: The target file to copy into (file name)
|
||||
:param target_path: The target file's path
|
||||
:return: None
|
||||
"""
|
||||
target_file_path = os.path.join(target_path, target_file)
|
||||
src_file_path = os.path.join(src_path, src_file)
|
||||
if os.path.exists(target_file_path):
|
||||
fs.unlock_file(target_file_path)
|
||||
shutil.copyfile(src_file_path, target_file_path)
|
||||
|
||||
@staticmethod
|
||||
def file_revert(file_name, parent_path=None, search_subdirs=False):
|
||||
# type: (str, str, bool) -> function
|
||||
"""
|
||||
Function decorator:
|
||||
Convenience version of file_revert_list for passing a single file
|
||||
Calls file_revert_list on a list one [file_name]
|
||||
:param file_name: The name of a file to backup (not path)
|
||||
:param parent_path: The root directory to search for the [file_names] (relative to the dev folder).
|
||||
Defaults to the project folder described by the inner function's workspace fixture
|
||||
:param search_subdirs: A boolean option for searching sub-directories for the files in [file_names]
|
||||
:return: function as per the function decorator pattern
|
||||
"""
|
||||
return FileManagement.file_revert_list([file_name], parent_path, search_subdirs)
|
||||
|
||||
@staticmethod
|
||||
def file_revert_list(file_names, parent_path=None, search_subdirs=False):
|
||||
# type: ([str], str, bool) -> function
|
||||
"""
|
||||
Function decorator:
|
||||
Collects file names specified in [file_names] in the [parent_path] directory.
|
||||
Backs up these files before executing the parameter to the "wrap" function.
|
||||
If the search_subdirs flag is True, searches all subdirectories of [parent_path] for files.
|
||||
:param file_names: A list of file names (not paths)
|
||||
:param parent_path: The root directory to search for the [file_names] (relative to the dev folder).
|
||||
Defaults to the project folder described by the inner function's workspace fixture
|
||||
:param search_subdirs: A boolean option for searching sub-directories for the files in [file_names]
|
||||
:return: function as per the function decorator pattern
|
||||
"""
|
||||
|
||||
def wrap(func):
|
||||
# type: (function) -> function
|
||||
def inner(self, request, workspace, editor, launcher_platform):
|
||||
# type: (...) -> None
|
||||
"""
|
||||
Inner function to wrap around decorated function. Function being decorated must match this
|
||||
functions parameter order.
|
||||
"""
|
||||
root_path = parent_path
|
||||
if root_path is not None:
|
||||
root_path = os.path.join(workspace.paths.engine_root(), root_path)
|
||||
else:
|
||||
# Default to project folder (AutomatedTesting)
|
||||
root_path = workspace.paths.project()
|
||||
|
||||
# Try to locate files
|
||||
try:
|
||||
file_list = FileManagement._find_files(file_names, root_path, search_subdirs)
|
||||
except RuntimeWarning as w:
|
||||
assert False, (
|
||||
w.args[0]
|
||||
+ " Please check use of search_subdirs; make sure you are using the correct parent directory."
|
||||
)
|
||||
|
||||
# Restore from backups
|
||||
for file_name, file_path in file_list.items():
|
||||
FileManagement._restore_file(file_name, file_path)
|
||||
|
||||
# Create backups for each discovered path for each specified filename
|
||||
for file_name, file_path in file_list.items():
|
||||
FileManagement._backup_file(file_name, file_path)
|
||||
|
||||
try:
|
||||
# Run the test
|
||||
func(self, request, workspace, editor, launcher_platform)
|
||||
finally:
|
||||
# Restore backups for each discovered path for each specified filename if they exist
|
||||
for file_name, file_path in file_list.items():
|
||||
FileManagement._restore_file(file_name, file_path)
|
||||
|
||||
return inner
|
||||
|
||||
return wrap
|
||||
|
||||
@staticmethod
|
||||
def file_override(target_file, src_file, parent_path=None, search_subdirs=False):
|
||||
# type: (str, str, str, bool) -> function
|
||||
"""
|
||||
Function decorator:
|
||||
Searches for [target_file] and [src_file] in [parent_path](relative to the project dev folder)
|
||||
and performs backup and file swapping. [target_file] is backed up and replaced with [src_file] before the
|
||||
decorated function executes.
|
||||
After the decorated function is executed [target_file] is restored to the state before being swapped.
|
||||
If [parent_path] is not specified, the project folder described by the current workspace will be used.
|
||||
If the search_subdirs flag is True, searches all subdirectories of [parent_path] for files.
|
||||
:param target_file: The name of the file being backed up and swapped into
|
||||
:param src_file: The name of the file to swap into [target_file]
|
||||
:param parent_path: The root directory to search for the [file_names] (relative to the dev folder).
|
||||
Defaults to the project folder described by the inner function's workspace fixture
|
||||
:param search_subdirs: A boolean option for searching sub-directories for the files in [file_names]
|
||||
:return: The decorated function
|
||||
"""
|
||||
|
||||
def wrap(func):
|
||||
def inner(self, request, workspace, editor, launcher_platform):
|
||||
"""
|
||||
Inner function to wrap around decorated function. Function being decorated must match this
|
||||
functions parameter order.
|
||||
"""
|
||||
root_path = parent_path
|
||||
if root_path is not None:
|
||||
root_path = os.path.join(workspace.paths.engine_root(), root_path)
|
||||
else:
|
||||
# Default to project folder (AutomatedTesting)
|
||||
root_path = workspace.paths.project()
|
||||
|
||||
# Try to locate both target and source files
|
||||
try:
|
||||
file_list = FileManagement._find_files([target_file, src_file], root_path, search_subdirs)
|
||||
except RuntimeWarning as w:
|
||||
assert False, (
|
||||
w.args[0]
|
||||
+ " Please check use of search_subdirs; make sure you are using the correct parent directory."
|
||||
)
|
||||
|
||||
FileManagement._restore_file(target_file, file_list[target_file])
|
||||
FileManagement._backup_file(target_file, file_list[target_file])
|
||||
FileManagement._copy_file(src_file, file_list[src_file], target_file, file_list[target_file])
|
||||
|
||||
try:
|
||||
# Run Test
|
||||
func(self, request, workspace, editor, launcher_platform)
|
||||
finally:
|
||||
FileManagement._restore_file(target_file, file_list[target_file])
|
||||
|
||||
return inner
|
||||
|
||||
return wrap
|
||||
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
|
||||
class Tests:
|
||||
passed = ("pass", "fail")
|
||||
|
||||
|
||||
def run():
|
||||
import os
|
||||
import sys
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
|
||||
helper.init_idle()
|
||||
Report.success(Tests.passed)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -0,0 +1,204 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
'''
|
||||
This unittest might have to be refactored once changes to Physmaterial_Editor.py are made.
|
||||
These changes will occur after the but, reverence below is resloved.
|
||||
Bug: LY-107392
|
||||
'''
|
||||
class Tests:
|
||||
opening_bad_file = ("Bad file could not be opened", "Bad file was opened")
|
||||
opened_good_file = ("Valid file was opened", "Valid file was not opened")
|
||||
opened_default_file = ("Default file was opened", "Default file was not opened")
|
||||
number_of_materials = ("File has correct number of materials", "File has wrong number of materials")
|
||||
material_deleted = ("Material successfully deleted", "Material was not deleted")
|
||||
material_modified = ("Material successfully modified", "Material was not modified")
|
||||
modify_attribute_error = ("Invalid attribute raises error", "Invalid attribute doesn't raise error")
|
||||
modify_combine_error = ("Invalid combine value raises error", "Invalid combine value doesn't raise error")
|
||||
modify_friction_error = ("Invalid friction value raises error", "Invalid restitution value doesn't raise error")
|
||||
delete_value_error = ("Nonexistent material can't be deleted", "Nonexistend material deleted")
|
||||
no_overwrite = ("File not updated with no write() call", "File updated with no write() call")
|
||||
overwrite_works = ("File can be updated", "File can not be updated")
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
Summary: Tests the utility of the Physmaterial_Editor
|
||||
|
||||
Level Description: Completely empty and used as method to run material editing methods from the editor
|
||||
|
||||
Expected Results: All Physmaterial tests work as expected.
|
||||
|
||||
Test Steps:
|
||||
1) Open Level
|
||||
2) Check that the correct files open
|
||||
3) Check library properties
|
||||
4) Check editor methods
|
||||
5) Check write() works as expected
|
||||
6) Close Editor
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Open 3D Engine Editor command terminal
|
||||
- Any passed and failed tests are written to the Editor.log file.
|
||||
Parsing the file or running a log_monitor are required to observe the test results.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
from Physmaterial_Editor import Physmaterial_Editor
|
||||
|
||||
# Test file names
|
||||
MATERIAL_LIBRARY = "UtilTest_Physmaterial_Editor_TestLibrary.physmaterial"
|
||||
MATERIAL_LIBRARY_BAD = "UtilTest_Physmaterial_Editor_TestLibrary_Bad.physmaterial"
|
||||
NUMBER_OF_MATERIALS = 21
|
||||
|
||||
# Test Functions
|
||||
def test_open_good_file():
|
||||
# type () -> bool
|
||||
try:
|
||||
Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def test_fail_opening_bad_file():
|
||||
# type () -> bool
|
||||
try:
|
||||
Physmaterial_Editor(MATERIAL_LIBRARY_BAD)
|
||||
except Exception:
|
||||
return True
|
||||
return False
|
||||
|
||||
def test_open_default_file():
|
||||
# type () -> bool
|
||||
try:
|
||||
Physmaterial_Editor()
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
def test_number_of_materials():
|
||||
# type () -> bool
|
||||
try:
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
raise Exception("Something went wrong with test_number_of materials")
|
||||
return material_library_object.number_of_materials == NUMBER_OF_MATERIALS
|
||||
|
||||
def test_can_modify_material_element():
|
||||
# type () -> bool
|
||||
try:
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
raise Exception("Something went wrong with test_can_modify_material_element")
|
||||
return material_library_object.modify_material("canopy", "StaticFriction", 1.56)
|
||||
|
||||
def test_bad_attribute_passed_modify_material():
|
||||
# type () -> bool
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
try:
|
||||
material_library_object.modify_material("canopy", "Friction", 1.56)
|
||||
except Exception:
|
||||
return True
|
||||
return False
|
||||
|
||||
def test_bad_value_passed_modify_combine():
|
||||
# type () -> bool
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
try:
|
||||
material_library_object.modify_material("canopy", "FrictionCombine", 1.56)
|
||||
except Exception:
|
||||
return True
|
||||
return False
|
||||
|
||||
def test_bad_value_passed_modify_friction():
|
||||
# type () -> bool
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
try:
|
||||
material_library_object.modify_material("canopy", "StaticFriction", "1.56")
|
||||
except Exception:
|
||||
return True
|
||||
return False
|
||||
|
||||
def test_can_delete_material():
|
||||
# type () -> bool
|
||||
try:
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
raise Exception("Something went wrong with test_can_delete_material")
|
||||
return material_library_object.delete_material("default")
|
||||
|
||||
def test_can_not_delete_nonexistant_material():
|
||||
# type () -> bool
|
||||
try:
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
raise Exception("Something went wrong with test_can_not_delete_nonexistant_material")
|
||||
return material_library_object.delete_material("default")
|
||||
|
||||
def test_file_does_not_update_without_overwrite():
|
||||
# type () -> bool
|
||||
try:
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
material_deleted = material_library_object.delete_material("fabric")
|
||||
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
raise Exception("Something went wrong with test_file_does_not_update_without_overwrite")
|
||||
return material_library_object.number_of_materials != (NUMBER_OF_MATERIALS - 1) and material_deleted
|
||||
|
||||
def test_file_does_update_with_overwrite():
|
||||
# type () -> bool
|
||||
try:
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
material_deleted = material_library_object.delete_material("glass")
|
||||
material_library_object.save_changes()
|
||||
material_library_object = Physmaterial_Editor(MATERIAL_LIBRARY)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
raise Exception("Something went wrong with test_file_does_update_with_overwrite")
|
||||
return material_library_object.number_of_materials == (NUMBER_OF_MATERIALS - 1) or material_deleted
|
||||
|
||||
# Test Script
|
||||
# 1) Open Level
|
||||
helper.init_idle()
|
||||
helper.open_level('physics', 'Physmaterial_Editor_Test')
|
||||
|
||||
# 2) Check that the correct files open
|
||||
Report.result(Tests.opening_bad_file, test_fail_opening_bad_file())
|
||||
Report.result(Tests.opened_good_file, test_open_good_file())
|
||||
Report.result(Tests.opened_default_file, test_open_default_file())
|
||||
|
||||
# 3) Check library properties
|
||||
Report.result(Tests.number_of_materials, test_number_of_materials())
|
||||
|
||||
# 4) Check editor methods
|
||||
Report.result(Tests.material_deleted, test_can_delete_material())
|
||||
Report.result(Tests.material_modified, test_can_modify_material_element())
|
||||
Report.result(Tests.modify_attribute_error, test_bad_attribute_passed_modify_material())
|
||||
Report.result(Tests.modify_combine_error, test_bad_value_passed_modify_combine())
|
||||
Report.result(Tests.modify_friction_error, test_bad_value_passed_modify_friction())
|
||||
Report.result(Tests.delete_value_error, test_can_not_delete_nonexistant_material())
|
||||
|
||||
# 5) Check write() works as expected
|
||||
Report.result(Tests.no_overwrite, test_file_does_not_update_without_overwrite())
|
||||
Report.result(Tests.overwrite_works, test_file_does_update_with_overwrite())
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -0,0 +1,12 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def run():
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -0,0 +1,12 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def run():
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
# fmt: off
|
||||
class Tests():
|
||||
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
|
||||
warning_found = ("ScriptCanvas Warning found when running level containing warning entity", "ScriptCanvas Warning NOT found when running level containing warning entity")
|
||||
error_found = ("PhysX Error found after openning level containing error entity", "PhysX Error NOT found after openning level containing error entity")
|
||||
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
|
||||
# fmt: on
|
||||
|
||||
def run():
|
||||
"""
|
||||
Summary:
|
||||
Checks that Tracer and the Trace notification EBus works propoerly.
|
||||
|
||||
Level Tracer_WarningEntity:
|
||||
Contains an Entity with a Script Canvas component with non-connected nodes.
|
||||
When entering into gamemode, Script Canvas should raise a Warning.
|
||||
|
||||
Level Tracer_ErrorEntity:
|
||||
Contains an Entity with a PhysX Collider Box with invalid extent (0, 1, 1).
|
||||
When opening the level, the collider should raise an Error.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
from editor_python_test_tools.utils import Tracer
|
||||
|
||||
helper.init_idle()
|
||||
|
||||
with Tracer() as entity_warning_tracer:
|
||||
def has_scriptcanvas_warning():
|
||||
return entity_warning_tracer.has_warnings and any('Script Canvas' in warningInfo.window for warningInfo in entity_warning_tracer.warnings)
|
||||
|
||||
helper.open_level("Utils", "Tracer_WarningEntity")
|
||||
helper.enter_game_mode(Tests.enter_game_mode)
|
||||
helper.wait_for_condition(has_scriptcanvas_warning, 1.0)
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
Report.result(Tests.warning_found, has_scriptcanvas_warning())
|
||||
|
||||
with Tracer() as entity_error_tracer:
|
||||
def has_physx_error():
|
||||
return entity_error_tracer.has_errors and any('PhysX' in errorInfo.window for errorInfo in entity_error_tracer.errors)
|
||||
|
||||
helper.open_level("Utils", "Tracer_ErrorEntity")
|
||||
helper.wait_for_condition(has_physx_error, 1.0)
|
||||
|
||||
Report.result(Tests.error_found, has_physx_error())
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
Reference in New Issue
Block a user