using System; using System.IO; using System.Threading; using NUnit.Framework; using UnityEditor.AddressableAssets.Settings; using UnityEditor.Build.Pipeline.Utilities; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TestTools; namespace UnityEditor.AddressableAssets.Tests { public abstract class AddressableAssetTestBase { protected const string k_TestConfigName = "AddressableAssetSettings.Tests"; protected string TestFolder => $"Assets/{TestFolderName}"; protected string TestFolderName => $"{GetType()}_Tests"; protected string ConfigFolder => TestFolder + "/Config"; protected string AddressablesFolder => $"Assets/AddressableAssetsData"; protected string GetAssetPath(string assetName) { return $"{TestFolder}/{assetName}"; } private AddressableAssetSettings m_Settings; protected AddressableAssetSettings Settings { get { if (!m_Settings || m_Settings.groups.IsNullOrEmpty()) m_Settings = AddressableAssetSettings.Create(ConfigFolder, k_TestConfigName, true, PersistSettings); return m_Settings; } } protected string m_AssetGUID; protected string[] m_SceneGuids; protected virtual bool PersistSettings { get { return true; } } [OneTimeSetUp] public void Init() { //TODO: Remove when NSImage warning issue on bokken is fixed Application.logMessageReceived += CheckLogForWarning; if (Directory.Exists(TestFolder)) { Debug.Log($"{GetType()} (init) - deleting {TestFolder}"); if (!AssetDatabase.DeleteAsset(TestFolder)) Directory.Delete(TestFolder); } if (Directory.Exists(AddressablesFolder)) { Debug.Log($"{GetType()} (init) - deleting {AddressablesFolder}"); if (!AssetDatabase.DeleteAsset(AddressablesFolder)) Directory.Delete(AddressablesFolder); } Debug.Log($"{GetType()} (init) - creating {TestFolder}"); AssetDatabase.CreateFolder("Assets", TestFolderName); AssetDatabase.CreateFolder(TestFolder, "Config"); Settings.labelTable.labelNames.Clear(); GameObject testObject = new GameObject("TestObject"); GameObject testObject1 = new GameObject("TestObject 1"); GameObject testObject2 = new GameObject("TestObject 2"); PrefabUtility.SaveAsPrefabAsset(testObject, TestFolder + "/test.prefab"); PrefabUtility.SaveAsPrefabAsset(testObject1, TestFolder + "/test 1.prefab"); PrefabUtility.SaveAsPrefabAsset(testObject2, TestFolder + "/test 2.prefab"); m_AssetGUID = AssetDatabase.AssetPathToGUID(TestFolder + "/test.prefab"); string scene1Path = TestFolder + "/contentUpdateScene1.unity"; string scene2Path = TestFolder + "/contentUpdateScene2.unity"; string scene3Path = TestFolder + "/contentUpdateScene3.unity"; Scene scene1 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); EditorSceneManager.SaveScene(scene1, scene1Path); Scene scene2 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); EditorSceneManager.SaveScene(scene2, scene2Path); Scene scene3 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); EditorSceneManager.SaveScene(scene3, scene3Path); //Clear out the active scene so it doesn't affect tests EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); m_SceneGuids = new string[] { AssetDatabase.AssetPathToGUID(scene1Path), AssetDatabase.AssetPathToGUID(scene2Path), AssetDatabase.AssetPathToGUID(scene3Path) }; OnInit(); //TODO: Remove when NSImage warning issue on bokken is fixed //Removing here in the event we didn't recieve any messages during the setup, we can respond appropriately to //logs in the tests. Application.logMessageReceived -= CheckLogForWarning; if (resetFailingMessages) LogAssert.ignoreFailingMessages = false; } private bool resetFailingMessages = false; //TODO: Remove when NSImage warning issue on bokken is fixed private void CheckLogForWarning(string condition, string stackTrace, LogType type) { LogAssert.ignoreFailingMessages = true; resetFailingMessages = true; } protected virtual void OnInit() { } [OneTimeTearDown] public void Cleanup() { OnCleanup(); if (Directory.Exists(TestFolder)) { Debug.Log($"{GetType()} - (cleanup) deleting {TestFolder}"); AssetDatabase.DeleteAsset(TestFolder); } if (Directory.Exists(AddressablesFolder)) { Debug.Log($"{GetType()} (init) - deleting {AddressablesFolder}"); if (!AssetDatabase.DeleteAsset(AddressablesFolder)) Directory.Delete(AddressablesFolder); } EditorBuildSettings.RemoveConfigObject(k_TestConfigName); } protected virtual void OnCleanup() { } protected string CreateAsset(string assetPath, string objectName = null) { if (string.IsNullOrEmpty(objectName)) objectName = Path.GetFileNameWithoutExtension(assetPath); GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube); go.name = objectName; //this is to ensure that bundles are different for every run. go.transform.localPosition = UnityEngine.Random.onUnitSphere; string directoryName = Path.GetDirectoryName(assetPath); CreateFolderDeep(directoryName); try { Assert.IsTrue(AssetDatabase.IsValidFolder(directoryName), "Attempting to save prefab to invalid Folder : " + directoryName); Assert.IsTrue(Directory.Exists(directoryName), "Folder is not in FileSystem, but is in ADB : " + directoryName); Assert.IsNotNull(go, "Attempting to save null GameObject to Prefab"); PrefabUtility.SaveAsPrefabAsset(go, assetPath); } catch (Exception e) { Debug.LogError($"Error while attempting to save prefab {objectName} to {assetPath} with Exception message {e.Message}"); throw e; } UnityEngine.Object.DestroyImmediate(go, false); return AssetDatabase.AssetPathToGUID(assetPath); } protected string CreateFolderDeep(string path) { path = path.Replace('\\', '/'); if (!path.StartsWith("Assets/", StringComparison.Ordinal)) return null; if (Directory.Exists(path)) { if (AssetDatabase.IsValidFolder(path)) return AssetDatabase.AssetPathToGUID(path); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); return AssetDatabase.AssetPathToGUID(path); } Directory.CreateDirectory(path); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); return AssetDatabase.AssetPathToGUID(path); } protected void ReloadSettings() { m_Settings = null; EditorBuildSettings.RemoveConfigObject(AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName); EditorBuildSettings.TryGetConfigObject(AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName, out m_Settings); } } }