initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,81 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.Build.Content;
using UnityEditor.Build.Pipeline;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEngine;
public class AddHashToBundleNameTaskTests : AddressableBuildTaskTestBase
{
[Test]
public void AddHashToBundleNameTask_DoesNotChangeHash_WhenAssetsChangeOrder()
{
//Setup
string path1 = $"{TempPath}/test1.prefab";
string path2 = $"{TempPath}/test2.prefab";
string path3 = $"{TempPath}/test3.prefab";
GUID guid1 = new GUID(CreateAsset(path1, "1"));
GUID guid2 = new GUID(CreateAsset(path2, "2"));
GUID guid3 = new GUID(CreateAsset(path3, "3"));
List<GUID> list1 = new List<GUID>()
{
guid1,
guid2,
guid3
};
List<GUID> list2 = new List<GUID>()
{
guid2,
guid1,
guid3
};
AddressableAssetGroup group = m_Settings.CreateGroup("AddHashTestGroup", false, false, false,
new List<AddressableAssetGroupSchema>());
m_Settings.CreateOrMoveEntry(guid1.ToString(), group);
m_Settings.CreateOrMoveEntry(guid2.ToString(), group);
m_Settings.CreateOrMoveEntry(guid3.ToString(), group);
IDependencyData dependencyData = new BuildDependencyData()
{
AssetInfo =
{
{guid1, new AssetLoadInfo() {referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid1, EditorUserBuildSettings.activeBuildTarget).ToList()}},
{guid2, new AssetLoadInfo() {referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid2, EditorUserBuildSettings.activeBuildTarget).ToList()}},
{
guid3, new AssetLoadInfo() {referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid3, EditorUserBuildSettings.activeBuildTarget).ToList()}
}
}
};
AddressableAssetsBuildContext context = new AddressableAssetsBuildContext()
{
Settings = m_Settings
};
AddHashToBundleNameTask addHashTask = new AddHashToBundleNameTask();
var field = typeof(AddHashToBundleNameTask).GetField("m_DependencyData", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(addHashTask, dependencyData);
//Test
RawHash hash1 = addHashTask.GetAssetsHash(list1, context);
RawHash hash2 = addHashTask.GetAssetsHash(list2, context);
//Assert
Assert.AreEqual(hash1, hash2);
//Cleanup
m_Settings.RemoveGroup(group);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 47c8f9980c2f63349a8fb20e6e1b5013
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,54 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
public class AddressableBuildTaskTestBase
{
protected AddressableAssetSettings m_Settings;
protected string TempPath
{
get { return $"Assets/{GetType().Name}TestData"; }
}
[SetUp]
public void Setup()
{
using (new IgnoreFailingLogMessage())
{
if (AssetDatabase.IsValidFolder(TempPath))
AssetDatabase.DeleteAsset(TempPath);
Directory.CreateDirectory(TempPath);
m_Settings = AddressableAssetSettings.Create(Path.Combine(TempPath, "Settings"),
"AddressableAssetSettings.Tests", false, true);
}
}
[TearDown]
public void Teardown()
{
// Many of the tests keep recreating assets in the same path, so we need to unload them completely so they don't get reused by the next test
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Settings));
Resources.UnloadAsset(m_Settings);
if (Directory.Exists(TempPath))
Directory.Delete(TempPath, true);
AssetDatabase.Refresh();
}
protected static string CreateAsset(string assetPath, string objectName)
{
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;
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
UnityEngine.Object.DestroyImmediate(go, false);
return AssetDatabase.AssetPathToGUID(assetPath);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fc8c72284fb9414ca3384e659772838
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,146 @@
#if UNITY_2021_2_OR_NEWER
using NUnit.Framework;
using System;
using System.IO;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using UnityEngine.AddressableAssets;
public class AddressablesPlayerBuildProcessorTests
{
protected static string TestFolder => $"Assets/AddressablesPlayerBuildProcessor_Tests";
protected static string ConfigFolder => TestFolder + "/Config";
AddressableAssetSettings m_Settings;
[SetUp]
public void Setup()
{
DirectoryUtility.DeleteDirectory(TestFolder, false);
Directory.CreateDirectory(ConfigFolder);
m_Settings = AddressableAssetSettings.Create(ConfigFolder, "AddressableAssetSettings.Tests", true, true);
CreateAddressablePrefab("test");
}
[TearDown]
public void Teardown()
{
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Settings));
Resources.UnloadAsset(m_Settings);
DirectoryUtility.DeleteDirectory(TestFolder, false);
AssetDatabase.Refresh();
}
AddressableAssetEntry CreateAddressablePrefab(string name, AddressableAssetGroup group = null)
{
string guid = CreateAsset(name);
return MakeAddressable(guid, null, group);
}
static string CreateAsset(string name)
{
string assetPath = $"{TestFolder}/{name}.prefab";
return CreateAsset(assetPath, name);
}
static string CreateAsset(string assetPath, string objectName)
{
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;
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
UnityEngine.Object.DestroyImmediate(go, false);
return AssetDatabase.AssetPathToGUID(assetPath);
}
AddressableAssetEntry MakeAddressable(string guid, string address = null, AddressableAssetGroup group = null)
{
if (group == null)
{
if (m_Settings.DefaultGroup == null)
throw new System.Exception("No DefaultGroup to assign Addressable to");
group = m_Settings.DefaultGroup;
}
var entry = m_Settings.CreateOrMoveEntry(guid, group, false, false);
entry.address = address == null ? entry.AssetPath : address;
return entry;
}
[Test]
[TestCase(AddressableAssetSettings.PlayerBuildOption.DoNotBuildWithPlayer, false)]
[TestCase(AddressableAssetSettings.PlayerBuildOption.BuildWithPlayer, false)]
[TestCase(AddressableAssetSettings.PlayerBuildOption.PreferencesValue, false)]
[TestCase(AddressableAssetSettings.PlayerBuildOption.PreferencesValue, true)]
public void PrepareAddressableBuildForPlayerBuild_ShouldBuildAddressables_CorrectForSettings(int settingValue, bool preferencesValue)
{
// Setup
m_Settings.BuildAddressablesWithPlayerBuild = (AddressableAssetSettings.PlayerBuildOption)settingValue;
bool deleteKey = !EditorPrefs.HasKey(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey);
bool previousPrefValue = EditorPrefs.GetBool(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey, true);
EditorPrefs.SetBool(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey, preferencesValue);
try
{
bool result = AddressablesPlayerBuildProcessor.ShouldBuildAddressablesForPlayerBuild(m_Settings);
if (m_Settings.BuildAddressablesWithPlayerBuild == AddressableAssetSettings.PlayerBuildOption.BuildWithPlayer)
Assert.IsTrue(result, "Addressables build was expected to set to build when preparing a Player Build");
else if (m_Settings.BuildAddressablesWithPlayerBuild == AddressableAssetSettings.PlayerBuildOption.DoNotBuildWithPlayer)
Assert.IsFalse(result, "Addressables build is not expected to set be build when preparing a Player Build");
else if (m_Settings.BuildAddressablesWithPlayerBuild == AddressableAssetSettings.PlayerBuildOption.DoNotBuildWithPlayer)
{
if (preferencesValue)
Assert.IsTrue(result, "Addressables build was expected to set to build when preparing a Player Build");
else
Assert.IsFalse(result, "Addressables build is not expected to set be build when preparing a Player Build");
}
}
catch (Exception e)
{
Assert.Fail("Unhandled Exception in Preparing for Addressables - With Exception: " + e);
}
finally
{
if (deleteKey)
EditorPrefs.DeleteKey(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey);
else
EditorPrefs.SetBool(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey, previousPrefValue);
}
}
[Test]
public void PrepareAddressableBuildForPlayerBuild_LinkXML_CopiedCorrectly()
{
string buildPath = Addressables.BuildPath + "/AddressablesLink/link.xml";
Directory.CreateDirectory(Addressables.BuildPath + "/AddressablesLink");
bool preexistingFile = File.Exists(buildPath);
if (!preexistingFile)
{
var textStream = File.CreateText(buildPath);
textStream.Write("link test file");
textStream.Close();
}
// do the test
string projectPath = Path.Combine(m_Settings.ConfigFolder, "link.xml");
try
{
AddressablesPlayerBuildProcessor.PrepareForPlayerbuild(m_Settings, null, false);
Assert.IsTrue(File.Exists(projectPath), "Link.xml file not found at project path when preparing for build");
}
// clean up
finally
{
AddressablesPlayerBuildProcessor.RemovePlayerBuildLinkXML(m_Settings);
if (!preexistingFile)
File.Delete(buildPath);
Assert.IsFalse(File.Exists(projectPath), "Link.xml file remains at the ProjectPath, link.xml expected to be deleted");
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41f1a51b4873d473d81bc70abb55d198
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,719 @@
using NUnit.Framework;
using System;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEditor.AddressableAssets.Build.Layout;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEditor.AddressableAssets.Tests;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.U2D;
using UnityEditor.U2D;
using UnityEditor.Presets;
public class BuildLayoutGenerationTaskTests
{
AddressableAssetSettings m_Settings;
AddressableAssetSettings Settings
{
get
{
if (m_Settings == null)
{
var path = Path.Combine(TempPath, "Settings", "/AddressableAssetSettings.Tests.asset");
m_Settings = AssetDatabase.LoadAssetAtPath<AddressableAssetSettings>(path);
}
return m_Settings;
}
}
static string kTempPath = "Assets/BuildLayoutGenerationTaskTestsData";
static string TempPath;
static int ExecCount;
bool m_PrevGenerateBuildLayout;
ProjectConfigData.ReportFileFormat m_PrevFileFormat;
[OneTimeSetUp]
public void OneTimeSetup()
{
ExecCount = 0;
}
[SetUp]
public void Setup()
{
TempPath = kTempPath + (ExecCount++).ToString();
foreach (var fileFormat in Enum.GetValues(typeof(ProjectConfigData.ReportFileFormat)))
{
string layoutFile = BuildLayoutGenerationTask.GetLayoutFilePathForFormat((ProjectConfigData.ReportFileFormat)fileFormat);
if (File.Exists(layoutFile))
File.Delete(layoutFile);
}
m_PrevGenerateBuildLayout = ProjectConfigData.GenerateBuildLayout;
m_PrevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
BuildScriptPackedMode.s_SkipCompilePlayerScripts = true;
ProjectConfigData.GenerateBuildLayout = true;
if (Directory.Exists(TempPath))
Directory.Delete(TempPath, true);
Directory.CreateDirectory(TempPath);
m_Settings = AddressableAssetSettings.Create(Path.Combine(TempPath, "Settings"), "AddressableAssetSettings.Tests", false, true);
}
[TearDown]
public void Teardown()
{
BuildScriptPackedMode.s_SkipCompilePlayerScripts = false;
ProjectConfigData.GenerateBuildLayout = m_PrevGenerateBuildLayout;
ProjectConfigData.BuildLayoutReportFileFormat = m_PrevFileFormat;
// Many of the tests keep recreating assets in the same path, so we need to unload them completely so they don't get reused by the next test
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(Settings));
Resources.UnloadAsset(Settings);
FileUtil.DeleteFileOrDirectory(TempPath);
FileUtil.DeleteFileOrDirectory(TempPath + ".meta");
AssetDatabase.Refresh();
}
string MakeAddressable(AddressableAssetGroup group, string guid, string address = null)
{
var entry = Settings.CreateOrMoveEntry(guid, group, false, false);
entry.address = address == null ? Path.GetFileNameWithoutExtension(entry.AssetPath) : address;
entry.BundleFileId = "GenericFileId";
return guid;
}
// Prefab asset emthods
static string CreatePrefabAsset(string name)
{
return CreatePrefabAsset($"{TempPath}/{name}.prefab", name);
}
static string CreatePrefabAsset(string assetPath, string objectName)
{
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;
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
UnityEngine.Object.DestroyImmediate(go, false);
return AssetDatabase.AssetPathToGUID(assetPath);
}
static string CreateScriptableObjectAsset(string assetPath, string objectName)
{
TestObject.Create(objectName, assetPath);
return AssetDatabase.AssetPathToGUID(assetPath);
}
string CreateAddressablePrefab(string name, AddressableAssetGroup group)
{
string guid = CreatePrefabAsset($"{TempPath}/{name}.prefab", name);
return MakeAddressable(group, guid);
}
string CreateAddressableScriptableObject(string name, AddressableAssetGroup group)
{
string guid = CreateScriptableObjectAsset($"{TempPath}/{name}.asset", name);
return MakeAddressable(group, guid);
}
bool DeletePrefab(string name)
{
string path = $"{TempPath}/{name}.prefab";
return AssetDatabase.DeleteAsset(path);
}
bool DeleteScriptableObject(string name)
{
string path = $"{TempPath}/{name}.asset";
return AssetDatabase.DeleteAsset(path);
}
// Texture asset creation
static string CreateTexture(string name, int size = 32)
{
string assetPath = $"{TempPath}/{name}.png";
var texture = new Texture2D(size, size);
var data = ImageConversion.EncodeToPNG(texture);
UnityEngine.Object.DestroyImmediate(texture);
File.WriteAllBytes(assetPath, data);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
return AssetDatabase.AssetPathToGUID(assetPath);
}
string CreateAddressableTexture(string name, AddressableAssetGroup group, int size = 32)
{
string guid = CreateTexture(name, size);
TextureImporter ti = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(guid));
ti.isReadable = false;
ti.SaveAndReimport();
return MakeAddressable(group, guid);
}
static string CreateSpriteAtlas(string name, string guidTargetTexture)
{
var sa = new SpriteAtlas();
var targetObjects = new UnityEngine.Object[] {AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(guidTargetTexture))};
sa.Add(targetObjects);
string saPath = $"{TempPath}/{name}.spriteAtlas";
AssetDatabase.CreateAsset(sa, saPath);
AssetDatabase.Refresh();
return AssetDatabase.AssetPathToGUID(saPath);
}
bool DeleteSpriteAtlas(string name)
{
string assetPath = $"{TempPath}/{name}.spriteAtlas";
return AssetDatabase.DeleteAsset(assetPath);
}
static string CreateSpriteTexture(string name, int size, bool includesSource)
{
string guid = CreateTexture(name, size);
string texturePath = AssetDatabase.GUIDToAssetPath(guid);
TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(guid));
importer.textureType = TextureImporterType.Sprite; // creates a sprite subobject
importer.spriteImportMode = SpriteImportMode.Single;
importer.SaveAndReimport();
return guid;
}
bool DeleteTexture(string name)
{
string assetPath = $"{TempPath}/{name}.png";
return AssetDatabase.DeleteAsset(assetPath);
}
/// <summary>
/// Adds a component to Prefab that references assetToReference
/// </summary>
/// <param name="prefabGUID"></param>
/// <param name="assetToReferenceGUID"></param>
void MakePefabReference(string prefabGUID, string assetToReferenceGUID)
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(prefabGUID));
UnityEngine.Object target = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(assetToReferenceGUID));
prefab.AddComponent<TestBehaviourWithReference>().Reference = target;
}
AddressableAssetGroup CreateGroup(string name)
{
return Settings.CreateGroup(name, false, false, false, null, typeof(BundledAssetGroupSchema));
}
void PrintText(BuildLayout layout)
{
MemoryStream stream = new MemoryStream();
BuildLayoutPrinter.WriteBundleLayout(stream, layout);
string report = Encoding.ASCII.GetString(stream.ToArray());
Debug.Log(report);
}
internal BuildLayout BuildAndExtractLayout()
{
try
{
BuildLayout layout = null;
BuildLayoutGenerationTask.s_LayoutCompleteCallback = (x, y) => layout = y;
Settings.BuildPlayerContentImpl();
return layout;
}
finally
{
BuildLayoutGenerationTask.s_LayoutCompleteCallback = null;
}
}
class WebExtractSession : IDisposable
{
public string DataDirectory;
public string[] Files;
public WebExtractSession(string filePath)
{
DataDirectory = filePath + "_data";
if (Directory.Exists(DataDirectory))
throw new Exception("Bundle data directory already exists");
var baseDir = Path.GetDirectoryName(EditorApplication.applicationPath);
var webExtractFiles = Directory.GetFiles(baseDir, "WebExtract*", SearchOption.AllDirectories);
string webExtractPath = webExtractFiles[0];
Assert.IsTrue(File.Exists(filePath), "Param filePath does not point to an existing file.");
var process = new System.Diagnostics.Process
{
StartInfo =
{
FileName = webExtractPath,
Arguments = string.Format(@"""{0}""", filePath),
UseShellExecute = false,
RedirectStandardOutput = true
}
};
process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
var exitCode = process.ExitCode;
process.Close();
Assert.AreEqual(0, exitCode);
Files = Directory.GetFiles(DataDirectory);
}
public void Dispose()
{
Directory.Delete(DataDirectory, true);
}
}
internal void AssertEditorBundleDetailsMatchPhysicalBundle(string bundlePath, BuildLayout.Bundle bundle)
{
Assert.AreEqual(new FileInfo(bundlePath).Length, bundle.FileSize);
using (var wes = new WebExtractSession(bundlePath))
{
Assert.AreEqual(bundle.Files.Sum(x => x.SubFiles.Count), wes.Files.Length);
foreach (BuildLayout.SubFile sf in bundle.Files.SelectMany(x => x.SubFiles))
{
string filename = Path.Combine(wes.DataDirectory, sf.Name);
Assert.AreEqual(sf.Size, new FileInfo(filename).Length);
}
}
}
[Test]
public void WhenBundleReferencesAnotherBundle_ExternalReferenceExists()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
AddressableAssetGroup group2 = null;
try
{
// setup
group = CreateGroup("Group1");
string prefabGUID = CreateAddressablePrefab("p1", group);
group2 = CreateGroup("Group2");
string g2p1GUID = CreateAddressablePrefab("g2p1", group2);
MakePefabReference(prefabGUID, g2p1GUID);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
CollectionAssert.Contains(layout.Groups[0].Bundles[0].Dependencies, layout.Groups[1].Bundles[0]);
Assert.AreEqual(layout.Groups[0].Bundles[0].Files[0].Assets[0].ExternallyReferencedAssets[0], layout.Groups[1].Bundles[0].Files[0].Assets[0]);
}
finally // cleanup
{
if (group != null)
Settings.RemoveGroup(group);
if (group2 != null)
Settings.RemoveGroup(group2);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeletePrefab("p1");
DeletePrefab("g2p1");
}
}
[Test]
public void WhenAssetImplicitlyPulledIntoBundle_ImplicitEntryAndReferencesCreated()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
try
{
// setup
group = CreateGroup("Group1");
string prefabGUID = CreateAddressablePrefab("p1", group);
string aGUID = CreatePrefabAsset("p2");
MakePefabReference(prefabGUID, aGUID);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
BuildLayout.DataFromOtherAsset oa = layout.Groups[0].Bundles[0].Files[0].OtherAssets.First(x => x.AssetPath.Contains("p2.prefab"));
Assert.AreEqual(aGUID, oa.AssetGuid);
}
finally // cleanup
{
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeletePrefab("p1");
DeletePrefab("p2");
}
}
[Test]
public void WhenBundleContainsMultipleFiles_FilesAndSizesMatchArchiveContent()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
string scenePath = $"{TempPath}/scene.unity";
AddressableAssetGroup groupScenes = null;
AddressableAssetGroup textureGroup = null;
try
{
// setup
groupScenes = CreateGroup("SceneGroup");
textureGroup = CreateGroup("TextureGroup");
Scene scene1 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
new GameObject().AddComponent<TestBehaviourWithReference>();
EditorSceneManager.SaveScene(scene1, scenePath);
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(scenePath), groupScenes);
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
CreateAddressableTexture("t1", textureGroup, 256);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
BundledAssetGroupSchema schema = Settings.groups.First(x => x.HasSchema<BundledAssetGroupSchema>()).GetSchema<BundledAssetGroupSchema>();
string path = schema.BuildPath.GetValue(Settings);
foreach (BuildLayout.Bundle bundle in layout.Groups.SelectMany(x => x.Bundles))
AssertEditorBundleDetailsMatchPhysicalBundle(Path.Combine(path, bundle.Name), bundle);
}
finally // cleanup
{
if (groupScenes != null)
Settings.RemoveGroup(groupScenes);
if (textureGroup != null)
Settings.RemoveGroup(textureGroup);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
AssetDatabase.DeleteAsset(scenePath);
DeleteTexture("t1");
}
}
// Even though slim writes is true, the system will enable it if it needs to generate a build layout report
[Test]
public void WhenSlimWriteResultsIsTrue_LayoutStillGenerated()
{
ProjectConfigData.ReportFileFormat fileFormat = ProjectConfigData.ReportFileFormat.TXT;
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(fileFormat);
AddressableAssetGroup group = null;
bool prevSlim = ScriptableBuildPipeline.slimWriteResults;
ProjectConfigData.ReportFileFormat prevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
try
{
// setup
ScriptableBuildPipeline.slimWriteResults = true;
ProjectConfigData.BuildLayoutReportFileFormat = fileFormat;
group = CreateGroup("Group1");
CreateAddressablePrefab("p1", group);
AssetDatabase.SaveAssets();
BuildAndExtractLayout();
FileAssert.Exists(layoutFilePath);
}
finally // cleanup
{
ScriptableBuildPipeline.slimWriteResults = prevSlim;
ProjectConfigData.BuildLayoutReportFileFormat = prevFileFormat;
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeletePrefab("p1");
}
}
[Test]
public void WhenBuildLayoutIsDisabled_BuildLayoutIsNotGenerated()
{
ProjectConfigData.ReportFileFormat fileFormat = ProjectConfigData.ReportFileFormat.TXT;
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(fileFormat);
AddressableAssetGroup group = null;
bool prevGenerateBuildLayout = ProjectConfigData.GenerateBuildLayout;
ProjectConfigData.ReportFileFormat prevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
try
{
// setup
ProjectConfigData.GenerateBuildLayout = false;
ProjectConfigData.BuildLayoutReportFileFormat = fileFormat;
group = CreateGroup("Group1");
CreateAddressablePrefab("p1", group);
AssetDatabase.SaveAssets();
BuildAndExtractLayout();
// Test
FileAssert.DoesNotExist(layoutFilePath);
}
finally // cleanup
{
ProjectConfigData.GenerateBuildLayout = prevGenerateBuildLayout;
ProjectConfigData.BuildLayoutReportFileFormat = prevFileFormat;
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeletePrefab("p1");
}
}
[Test]
[TestCase(ProjectConfigData.ReportFileFormat.TXT)]
[TestCase(ProjectConfigData.ReportFileFormat.JSON)]
public void WhenBuildLayoutIsEnabled_BuildLayoutIsGenerated(ProjectConfigData.ReportFileFormat format)
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(format);
AddressableAssetGroup group = null;
bool prevGenerateBuildLayout = ProjectConfigData.GenerateBuildLayout;
ProjectConfigData.ReportFileFormat prevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
try
{
// setup
ProjectConfigData.GenerateBuildLayout = true;
ProjectConfigData.BuildLayoutReportFileFormat = format;
group = CreateGroup("Group1");
CreateAddressablePrefab("p1", group);
AssetDatabase.SaveAssets();
BuildAndExtractLayout();
// Test
FileAssert.Exists(layoutFilePath);
if (format == ProjectConfigData.ReportFileFormat.JSON)
{
string text = File.ReadAllText(layoutFilePath);
var layout = JsonUtility.FromJson<BuildLayout>(text);
Assert.IsNotNull(layout);
}
}
finally // cleanup
{
ProjectConfigData.GenerateBuildLayout = prevGenerateBuildLayout;
ProjectConfigData.BuildLayoutReportFileFormat = prevFileFormat;
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeletePrefab("p1");
}
}
[Test]
public void WhenAssetHasStreamedData_IsReportedCorrectly()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
try
{
// setup
group = CreateGroup("Group1");
CreateAddressableTexture("t1", group, 256);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
Assert.IsTrue(layout.Groups[0].Bundles[0].Files[0].Assets[0].StreamedSize != 0);
BuildLayout.SubFile f = layout.Groups[0].Bundles[0].Files[0].SubFiles.First(x => x.Name.EndsWith(".resS"));
Assert.IsFalse(f.IsSerializedFile);
}
finally // cleanup
{
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeleteTexture("t1");
}
}
[Test]
public void WhenAllContentsOfAnAssetAreStripped_ExplicitAssetHasNoObjects()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
string assetPath = $"{TempPath}/testpreset.preset";
try
{
// setup
Material obj = new Material(Shader.Find("Transparent/Diffuse"));
Preset myPreset = new Preset(obj);
AssetDatabase.CreateAsset(myPreset, assetPath);
GameObject.DestroyImmediate(obj);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
string guid = AssetDatabase.AssetPathToGUID(assetPath);
group = CreateGroup("Group1");
MakeAddressable(group, guid);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
Assert.AreEqual(0, layout.Groups[0].Bundles[0].Files[0].Assets[0].SerializedSize);
}
finally // cleanup
{
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
AssetDatabase.DeleteAsset(assetPath);
}
}
class SpritePackerScope : IDisposable
{
SpritePackerMode m_PrevMode;
public SpritePackerScope(SpritePackerMode mode)
{
m_PrevMode = EditorSettings.spritePackerMode;
EditorSettings.spritePackerMode = mode;
}
public void Dispose()
{
EditorSettings.spritePackerMode = m_PrevMode;
}
}
[Test]
public void WhenReferencedObjectIdentifiedWithFilename_ObjectRepresentedInDataFromOtherAssets()
{
using (new SpritePackerScope(SpritePackerMode.BuildTimeOnlyAtlas))
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
try
{
// setup
BuildCache.PurgeCache(false);
group = CreateGroup("Group1");
string textureGUID = CreateSpriteTexture("spritetexture", 256, false);
MakeAddressable(group, CreateSpriteAtlas("atlas", textureGUID));
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
BuildLayout.DataFromOtherAsset otherAssets = layout.Groups[0].Bundles[0].Files[0].Assets[0].InternalReferencedOtherAssets[0];
Assert.AreEqual(2, layout.Groups[0].Bundles[0].Files[0].Assets[0].InternalReferencedOtherAssets.Count);
CollectionAssert.Contains(otherAssets.ReferencingAssets, layout.Groups[0].Bundles[0].Files[0].Assets[0]);
}
finally // cleanup
{
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeleteSpriteAtlas("atlas");
DeleteTexture("spritetexture");
}
}
}
[Test]
public void WhenBuildRemoteCatalogIsDisabled_BuildLayoutContainsCatalogHash()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
bool prevBuildRemoteCatalog = Settings.BuildRemoteCatalog;
try
{
// setup
group = CreateGroup("Group1");
CreateAddressablePrefab("p1", group);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
Assert.IsFalse(string.IsNullOrEmpty(layout.AddressablesRuntimeSettings.CatalogHash), "Catalog Hash was not correctly written to the Layout");
Assert.AreEqual(32, layout.AddressablesRuntimeSettings.CatalogHash.Length, "Catalog Hash was not correctly written to the Layout, incorrect size for hash");
Assert.AreEqual(32, layout.BuildResultHash.Length, "Build is expected to have a result hash for the build");
}
finally // cleanup
{
Settings.BuildRemoteCatalog = prevBuildRemoteCatalog;
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeletePrefab("p1");
}
}
[Test]
public void WhenBuildContainsMonoScripts_LayoutDoesNotHaveReferencesToMonoScriptAssets()
{
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
AddressableAssetGroup group = null;
bool prevBuildRemoteCatalog = Settings.BuildRemoteCatalog;
try
{
// setup
group = CreateGroup("Group1");
CreateAddressableScriptableObject("so1", group);
AssetDatabase.SaveAssets();
BuildLayout layout = BuildAndExtractLayout();
// Test
foreach (BuildLayout.ExplicitAsset explicitAsset in BuildLayoutHelpers.EnumerateAssets(layout))
{
foreach (var referencedAsset in explicitAsset.InternalReferencedExplicitAssets)
{
Assert.IsNotNull(referencedAsset, "Referenced Asset was null, this was likely a stripped MonoScript");
Assert.IsTrue(!referencedAsset.AssetPath.EndsWith(".cs") && referencedAsset.AssetPath.EndsWith(".dll"));
}
foreach (var referencedAsset in explicitAsset.ExternallyReferencedAssets)
{
Assert.IsNotNull(referencedAsset, "Referenced Asset was null, this was likely a stripped MonoScript");
Assert.IsTrue(!referencedAsset.AssetPath.EndsWith(".cs") && referencedAsset.AssetPath.EndsWith(".dll"));
}
foreach (var referencedAsset in explicitAsset.InternalReferencedOtherAssets)
{
Assert.IsNotNull(referencedAsset, "Referenced Asset was null, this was likely a stripped MonoScript");
Assert.IsTrue(!referencedAsset.AssetPath.EndsWith(".cs") && referencedAsset.AssetPath.EndsWith(".dll"));
}
}
}
finally // cleanup
{
Settings.BuildRemoteCatalog = prevBuildRemoteCatalog;
if (group != null)
Settings.RemoveGroup(group);
if (File.Exists(layoutFilePath))
File.Delete(layoutFilePath);
DeleteScriptableObject("so1");
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 041ea21fa30a4a34fa6cfe55505b452c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.GUI;
using UnityEngine;
using UnityEngine.TestTools;
using static UnityEditor.AddressableAssets.GUI.AddressableAssetsSettingsGroupEditor;
namespace UnityEditor.AddressableAssets.Tests
{
public class BuildMenuTests : AddressableAssetTestBase
{
[HideBuildMenuInUI]
public class BaseTestBuildMenu : AddressableAssetsSettingsGroupEditor.IAddressablesBuildMenu
{
public virtual string BuildMenuPath
{
get => "";
}
public virtual bool SelectableBuildScript
{
get => true;
}
public virtual int Order
{
get => 0;
}
public virtual bool OnPrebuild(AddressablesDataBuilderInput input)
{
return true;
}
public virtual bool OnPostbuild(AddressablesDataBuilderInput input, AddressablesPlayerBuildResult result)
{
return true;
}
}
public class TestBuildMenu : BaseTestBuildMenu
{
public override bool OnPrebuild(AddressablesDataBuilderInput input)
{
Debug.Log("Pre Invoked");
return true;
}
public override bool OnPostbuild(AddressablesDataBuilderInput input, AddressablesPlayerBuildResult result)
{
Debug.Log("Post Invoked");
return true;
}
}
public class TestBuildMenuOrderZero : BaseTestBuildMenu
{
public override string BuildMenuPath => "Zero";
public override int Order => 0;
}
public class TestBuildMenuOrderMinusOne : BaseTestBuildMenu
{
public override string BuildMenuPath => "MinusOne";
public override int Order => -1;
}
public class TestBuildMenuOrderOne : BaseTestBuildMenu
{
public override string BuildMenuPath => "One";
public override int Order => 1;
}
public class TestBuildMenu1_BuildPathTest : BaseTestBuildMenu
{
public override string BuildMenuPath => "Test";
}
public class TestBuildMenu2_BuildPathTest : BaseTestBuildMenu
{
public override string BuildMenuPath => "Test";
}
[Test]
public void BuildMenu_BuildCorrectlyCallPreAndPost()
{
AddressableAssetsSettingsGroupEditor.BuildMenuContext context =
new AddressableAssetsSettingsGroupEditor.BuildMenuContext();
context.BuildMenu = new TestBuildMenu();
context.buildScriptIndex = -1;
context.Settings = Settings;
// Test
LogAssert.Expect(LogType.Log, "Pre Invoked");
LogAssert.Expect(LogType.Log, "Post Invoked");
AddressableAssetsSettingsGroupEditor.OnBuildAddressables(context);
}
[Test]
public void BuildMenu_CreateBuildMenus_CorrectOrder()
{
List<Type> menuTypes = new List<Type>();
// 1, -1, 0
menuTypes.Add(typeof(TestBuildMenuOrderOne));
menuTypes.Add(typeof(TestBuildMenuOrderMinusOne));
menuTypes.Add(typeof(TestBuildMenuOrderZero));
var menus = AddressableAssetsSettingsGroupEditor.CreateBuildMenus(menuTypes, true);
Assert.AreEqual(3, menus.Count, "Failed to get the correct number of build menus");
string orderStr = menus[0].Order.ToString();
orderStr += "," + menus[1].Order.ToString();
orderStr += "," + menus[2].Order.ToString();
Assert.AreEqual("-1,0,1", orderStr, "Menus not in the correct order");
}
[Test]
public void BuildMenu_RemovesConflictingBuildPaths()
{
List<Type> menuTypes = new List<Type>();
menuTypes.Add(typeof(TestBuildMenu1_BuildPathTest));
menuTypes.Add(typeof(TestBuildMenu2_BuildPathTest));
LogAssert.Expect(LogType.Warning,
"Trying to new build menu [UnityEditor.AddressableAssets.Tests.BuildMenuTests+TestBuildMenu2_BuildPathTest] with path \"Test\". But an existing type already exists with that path, [UnityEditor.AddressableAssets.Tests.BuildMenuTests+TestBuildMenu1_BuildPathTest].");
var menus = AddressableAssetsSettingsGroupEditor.CreateBuildMenus(menuTypes, true);
Assert.AreEqual(1, menus.Count, "Failed to get the correct number of build menus");
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3331e5d5506b4b59975f5b7aee249b67
timeCreated: 1649164850

View file

@ -0,0 +1,22 @@
using System;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEngine;
namespace UnityEditor.AddressableAssets.Tests
{
public class BuildScriptFastTests : AddressableAssetTestBase
{
[Test]
public void FastModeScript_CannotBuildPlayerContent()
{
var buildScript = ScriptableObject.CreateInstance<BuildScriptFastMode>();
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
Assert.IsTrue(buildScript.CanBuildData<AddressableAssetBuildResult>());
Assert.IsTrue(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f1a1c0162fa02cb42ae827251833e0bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,126 @@
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEngine;
public class BuildScriptPackedIntegrationTests
{
string CreateTexture(string path)
{
var data = ImageConversion.EncodeToPNG(new Texture2D(32, 32));
File.WriteAllBytes(path, data);
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
return AssetDatabase.AssetPathToGUID(path);
}
static IDataBuilder GetBuilderOfType(AddressableAssetSettings settings, Type modeType)
{
foreach (var db in settings.DataBuilders)
{
var b = db;
if (b.GetType() == modeType)
return b as IDataBuilder;
}
throw new Exception("DataBuilder not found");
}
protected string m_SingleTestBuildFolder;
protected string m_SingleTestAssetFolder;
void DeleteSingleTestDirectories()
{
if (Directory.Exists(m_SingleTestBuildFolder))
Directory.Delete(m_SingleTestBuildFolder, true);
if (Directory.Exists(m_SingleTestAssetFolder))
Directory.Delete(m_SingleTestAssetFolder, true);
}
string m_SettingsPath;
AddressableAssetSettings m_Settings;
AddressableAssetSettings Settings
{
get
{
if (m_Settings == null)
m_Settings = AssetDatabase.LoadAssetAtPath<AddressableAssetSettings>(m_SettingsPath);
return m_Settings;
}
}
[SetUp]
public void Setup()
{
m_SingleTestBuildFolder = "Temp/TestBuild";
m_SingleTestAssetFolder = "Assets/SingleTestFolder";
DeleteSingleTestDirectories();
Directory.CreateDirectory(m_SingleTestBuildFolder);
Directory.CreateDirectory(m_SingleTestAssetFolder);
AddressableAssetSettings settings = AddressableAssetSettings.Create(Path.Combine(m_SingleTestAssetFolder, "Settings"), "AddressableAssetSettings.Tests", false, true);
m_SettingsPath = settings.AssetPath;
}
[TearDown]
public void TearDown()
{
DeleteSingleTestDirectories();
}
[Test]
public void IncrementalBuild_WhenBundleTimestampUnchanged_DoesNotCopy()
{
AddressableAssetBuildResult result;
var group = Settings.CreateGroup("MyTestGroup", true, false, false, null, typeof(BundledAssetGroupSchema));
var spriteEntry = Settings.CreateOrMoveEntry(CreateTexture($"{m_SingleTestAssetFolder}/testTexture.png"), group, false, false);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalBuildPath, m_SingleTestBuildFolder);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalLoadPath, "Library/LocalLoadPath");
IDataBuilder b = GetBuilderOfType(Settings, typeof(BuildScriptPackedMode));
b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
string[] buildFiles = Directory.GetFiles(m_SingleTestBuildFolder);
// Build again with a lock on the output bundle. This is how we ensure that the bundle is not written again
using (File.Open(buildFiles[0], FileMode.Open, FileAccess.ReadWrite, FileShare.None))
result = b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
Assert.AreEqual(1, buildFiles.Length, "There should only be one bundle file in the build output folder");
Assert.IsTrue(string.IsNullOrEmpty(result.Error));
}
[Test]
public void IncrementalBuild_WhenBundleTimestampChanges_CopiesNewFile()
{
var group = Settings.CreateGroup("MyTestGroup", true, false, false, null, typeof(BundledAssetGroupSchema));
var spriteEntry = Settings.CreateOrMoveEntry(CreateTexture($"{m_SingleTestAssetFolder}/testTexture.png"), group, false, false);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalBuildPath, m_SingleTestBuildFolder);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalLoadPath, "Library/LocalLoadPath");
IDataBuilder b = GetBuilderOfType(Settings, typeof(BuildScriptPackedMode));
b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
string[] buildFiles = Directory.GetFiles(m_SingleTestBuildFolder);
byte[] initialBundleBytes = File.ReadAllBytes(buildFiles[0]);
File.Delete(buildFiles[0]);
File.WriteAllText(buildFiles[0], "content");
File.SetLastWriteTime(buildFiles[0], new DateTime(2019, 1, 1));
b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
Assert.AreEqual(1, buildFiles.Length, "There should only be one bundle file in the build output folder");
CollectionAssert.AreEqual(initialBundleBytes, File.ReadAllBytes(buildFiles[0]));
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b47f3ece14ba6b74e883481b6ef86d53
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.Initialization;
namespace UnityEditor.AddressableAssets.Tests
{
public class BuildScriptPackedPlayTests : AddressableAssetTestBase
{
protected override void OnInit()
{
//Player data must be built before PackPlaymode can be used.
var input = new AddressablesDataBuilderInput(Settings);
ScriptableObject.CreateInstance<BuildScriptPackedMode>().BuildData<AddressableAssetBuildResult>(input);
}
[Test]
public void PackedPlayModeScript_CannotBuildPlayerContent()
{
var buildScript = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
Assert.IsTrue(buildScript.CanBuildData<AddressableAssetBuildResult>());
Assert.IsTrue(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
}
[Test]
public void PackedPlayModeScript_AppendsBuildLog_ForNonStandaloneBuildTarget()
{
//Setup
BuildScriptPackedPlayMode buildScript = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
AddressablesDataBuilderInput input = new AddressablesDataBuilderInput(Settings);
input.SetAllValues(Settings, BuildTargetGroup.Android, BuildTarget.Android, "");
ScriptableObject.CreateInstance<BuildScriptPackedMode>().BuildData<AddressableAssetBuildResult>(input);
//Test
buildScript.BuildData<AddressablesPlayModeBuildResult>(input);
var buildLogPath = Addressables.BuildPath + "/buildLogs.json";
var logs = JsonUtility.FromJson<PackedPlayModeBuildLogs>(File.ReadAllText(buildLogPath));
//Cleanup (done early in case of test failure)
File.Delete(buildLogPath);
//Assert
Assert.AreEqual(1, logs.RuntimeBuildLogs.Count);
Assert.AreEqual(LogType.Warning, logs.RuntimeBuildLogs[0].Type);
Assert.AreEqual($"Asset bundles built with build target {input.Target} may not be compatible with running in the Editor.", logs.RuntimeBuildLogs[0].Message);
}
[Test]
public void PackedPlayModeScript_AppendsBuildLog_ForInvalidBuildTarget()
{
//Setup
BuildScriptPackedPlayMode buildScript = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
AddressablesDataBuilderInput input = new AddressablesDataBuilderInput(Settings);
var settingsPath = Addressables.BuildPath + "/settings.json";
var rtd = JsonUtility.FromJson<ResourceManagerRuntimeData>(File.ReadAllText(settingsPath));
var buildLogPath = Addressables.BuildPath + "/buildLogs.json";
string storedBuildTarget = rtd.BuildTarget;
string invalidTarget = rtd.BuildTarget = "NotAValidBuildTarget";
File.WriteAllText(settingsPath, JsonUtility.ToJson(rtd));
//Test
buildScript.BuildData<AddressablesPlayModeBuildResult>(input);
var logs = JsonUtility.FromJson<PackedPlayModeBuildLogs>(File.ReadAllText(buildLogPath));
//Cleanup (done early in case of test failure)
File.Delete(buildLogPath);
rtd.BuildTarget = storedBuildTarget;
File.WriteAllText(settingsPath, JsonUtility.ToJson(rtd));
//Assert
Assert.AreEqual(1, logs.RuntimeBuildLogs.Count);
Assert.AreEqual(LogType.Warning, logs.RuntimeBuildLogs[0].Type);
Assert.AreEqual($"Unable to parse build target from initialization data: '{invalidTarget}'.", logs.RuntimeBuildLogs[0].Message);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49c2c229315d04249b13bbf17069f486
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f2eff97e91ec624b8d35cecfb1ccf38
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,632 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.TestTools;
namespace UnityEditor.AddressableAssets.Tests
{
public class BuildScriptTests : AddressableAssetTestBase
{
[TestFixture]
class StreamingAssetTests : AddressableAssetTestBase
{
[SetUp]
public void Setup()
{
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
}
[TearDown]
public void TearDown()
{
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
}
[Test]
public void ClearCachedData_CleansStreamingAssetFolder()
{
var context = new AddressablesDataBuilderInput(Settings);
int builderCount = 0;
for (int i = 0; i < Settings.DataBuilders.Count; i++)
{
var builder = Settings.DataBuilders[i] as IDataBuilder;
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
{
builderCount++;
var existingFiles = new HashSet<string>();
if (System.IO.Directory.Exists("Assets/StreamingAssets"))
{
foreach (var f in System.IO.Directory.GetFiles("Assets/StreamingAssets"))
existingFiles.Add(f);
}
builder.BuildData<AddressablesPlayerBuildResult>(context);
builder.ClearCachedData();
if (System.IO.Directory.Exists("Assets/StreamingAssets"))
{
foreach (var f in System.IO.Directory.GetFiles("Assets/StreamingAssets"))
Assert.IsTrue(existingFiles.Contains(f), string.Format("Data Builder {0} did not clean up file {1}", builder.Name, f));
}
}
}
Assert.IsTrue(builderCount > 0);
}
[Test]
public void Folder_WithSubAssets_GetsBundleFileIdAssigned_DuringBuild()
{
var context = new AddressablesDataBuilderInput(Settings);
string folderGuid = AssetDatabase.CreateFolder(TestFolder, "FolderAsset");
string folderPath = $"{TestFolder}/FolderAsset";
PrefabUtility.SaveAsPrefabAsset(new GameObject(), $"{folderPath}/subfolderprefab.prefab");
AddressableAssetEntry folderEntry = Settings.CreateOrMoveEntry(folderGuid, Settings.DefaultGroup);
Assert.IsTrue(string.IsNullOrEmpty(folderEntry.BundleFileId));
Settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(folderEntry.IsFolder);
Assert.IsFalse(string.IsNullOrEmpty(folderEntry.BundleFileId));
//Cleanup
AssetDatabase.DeleteAsset(folderPath);
Settings.RemoveAssetEntry(folderEntry);
}
[Test]
public void Folder_WithNoSubAssets_DoesNotThrowErrorDuringBuild()
{
var context = new AddressablesDataBuilderInput(Settings);
string folderGuid = AssetDatabase.CreateFolder(TestFolder, "FolderAsset");
string folderPath = $"{TestFolder}/FolderAsset";
AddressableAssetEntry folderEntry = Settings.CreateOrMoveEntry(folderGuid, Settings.DefaultGroup);
Assert.IsTrue(string.IsNullOrEmpty(folderEntry.BundleFileId));
Settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(folderEntry.IsFolder);
Assert.IsTrue(string.IsNullOrEmpty(folderEntry.BundleFileId));
//Cleanup
AssetDatabase.DeleteAsset(folderPath);
Settings.RemoveAssetEntry(folderEntry);
}
[Test]
public void Folder_DoesNotAssignBundleFileId_ForDynamicallyCreatedSubEntries()
{
var context = new AddressablesDataBuilderInput(Settings);
string folderGuid = AssetDatabase.CreateFolder(TestFolder, "FolderAsset");
string folderPath = $"{TestFolder}/FolderAsset";
PrefabUtility.SaveAsPrefabAsset(new GameObject(), $"{folderPath}/subfolderprefab.prefab");
AddressableAssetEntry folderEntry = Settings.CreateOrMoveEntry(folderGuid, Settings.DefaultGroup);
Settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
Assert.True(string.IsNullOrEmpty(folderEntry.SubAssets[0].BundleFileId));
//Cleanup
AssetDatabase.DeleteAsset(folderPath);
Settings.RemoveAssetEntry(folderEntry);
}
#if !UNITY_2021_2_OR_NEWER
[Test]
public void CopiedStreamingAssetAreCorrectlyDeleted_DirectoriesWithoutImport()
{
var context = new AddressablesDataBuilderInput(Settings);
int builderCount = 0;
for (int i = 0; i < Settings.DataBuilders.Count; i++)
{
var builder = Settings.DataBuilders[i] as IDataBuilder;
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
{
builderCount++;
// confirm that StreamingAssets does not exists before the test
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
builder.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(Directory.Exists(Addressables.BuildPath));
AddressablesPlayerBuildProcessor.CopyTemporaryPlayerBuildData();
builder.ClearCachedData();
Assert.IsTrue(Directory.Exists(Addressables.PlayerBuildDataPath));
AddressablesPlayerBuildProcessor.CleanTemporaryPlayerBuildData();
Assert.IsFalse(Directory.Exists(Addressables.PlayerBuildDataPath));
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
}
}
Assert.IsTrue(builderCount > 0);
}
[Test]
public void CopiedStreamingAssetAreCorrectlyDeleted_MetaFilesWithImport()
{
var context = new AddressablesDataBuilderInput(Settings);
int builderCount = 0;
for (int i = 0; i < Settings.DataBuilders.Count; i++)
{
var builder = Settings.DataBuilders[i] as IDataBuilder;
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
{
builderCount++;
// confirm that StreamingAssets does not exists before the test
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
builder.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(Directory.Exists(Addressables.BuildPath));
AddressablesPlayerBuildProcessor.CopyTemporaryPlayerBuildData();
builder.ClearCachedData();
// confirm that PlayerBuildDataPath is imported to AssetDatabase
AssetDatabase.Refresh();
Assert.IsTrue(Directory.Exists(Addressables.PlayerBuildDataPath));
Assert.IsTrue(File.Exists(Addressables.PlayerBuildDataPath + ".meta"));
string relativePath = Addressables.PlayerBuildDataPath.Replace(Application.dataPath, "Assets");
Assert.IsTrue(AssetDatabase.IsValidFolder(relativePath), "Copied StreamingAssets folder was not importer as expected");
AddressablesPlayerBuildProcessor.CleanTemporaryPlayerBuildData();
Assert.IsFalse(Directory.Exists(Addressables.PlayerBuildDataPath));
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
}
}
Assert.IsTrue(builderCount > 0);
}
[Test]
public void CopiedStreamingAssetAreCorrectlyDeleted_WithExistingFiles()
{
var context = new AddressablesDataBuilderInput(Settings);
int builderCount = 0;
for (int i = 0; i < Settings.DataBuilders.Count; i++)
{
var builder = Settings.DataBuilders[i] as IDataBuilder;
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
{
builderCount++;
// confirm that StreamingAssets does not exists before the test
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
// create StreamingAssets and an extra folder as existing content
AssetDatabase.CreateFolder("Assets", "StreamingAssets");
AssetDatabase.CreateFolder("Assets/StreamingAssets", "extraFolder");
builder.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(Directory.Exists(Addressables.BuildPath));
AddressablesPlayerBuildProcessor.CopyTemporaryPlayerBuildData();
builder.ClearCachedData();
Assert.IsTrue(Directory.Exists(Addressables.PlayerBuildDataPath));
AddressablesPlayerBuildProcessor.CleanTemporaryPlayerBuildData();
Assert.IsFalse(Directory.Exists(Addressables.PlayerBuildDataPath));
Assert.IsTrue(Directory.Exists("Assets/StreamingAssets"));
Assert.IsTrue(Directory.Exists("Assets/StreamingAssets/extraFolder"));
AssetDatabase.DeleteAsset("Assets/StreamingAssets");
}
}
Assert.IsTrue(builderCount > 0);
}
#else
[Test]
public void AddressablesBuildPlayerProcessor_IncludeAdditionalStreamingAssetsWhenExist()
{
string path = Addressables.BuildPath;
Directory.CreateDirectory(path);
var paths = AddressablesPlayerBuildProcessor.GetStreamingAssetPaths();
Assert.AreEqual(1, paths.Count, "StreamingAssets paths expected to include Addressables.BuildPath");
// cleanup
Directory.Delete(path);
}
[Test]
public void AddressablesBuildPlayerProcessor_DoesntIncludeAdditionalStreamingAssetsWhenDontExist()
{
if (Directory.Exists(Addressables.BuildPath))
DirectoryUtility.DeleteDirectory(Addressables.BuildPath, false);
var paths = AddressablesPlayerBuildProcessor.GetStreamingAssetPaths();
Assert.AreEqual(0, paths.Count, "StreamingAssets paths are expected to be empty");
// cleanup
}
#endif
}
[Test]
public void BuildScriptBase_FailsCanBuildData()
{
var buildScript = ScriptableObject.CreateInstance<BuildScriptBase>();
Assert.IsFalse(buildScript.CanBuildData<IDataBuilderResult>());
Assert.IsFalse(buildScript.CanBuildData<AddressableAssetBuildResult>());
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
}
internal class BuildScriptTestClass : BuildScriptBase
{
public override string Name
{
get { return "Test Script"; }
}
public override bool CanBuildData<T>()
{
return typeof(T).IsAssignableFrom(typeof(AddressablesPlayModeBuildResult));
}
protected override TResult BuildDataImplementation<TResult>(AddressablesDataBuilderInput builderInput)
{
Debug.LogError("Inside BuildDataInternal for test script!");
return base.BuildDataImplementation<TResult>(builderInput);
}
}
[Test]
public void BuildScript_DoesNotBuildWrongDataType()
{
var context = new AddressablesDataBuilderInput(Settings);
var baseScript = ScriptableObject.CreateInstance<BuildScriptTestClass>();
baseScript.BuildData<AddressablesPlayerBuildResult>(context);
LogAssert.Expect(LogType.Error, new Regex("Data builder Test Script cannot build requested type.*"));
baseScript.BuildData<AddressablesPlayModeBuildResult>(context);
LogAssert.Expect(LogType.Error, "Inside BuildDataInternal for test script!");
}
[Test]
public void GetNameWithHashNaming_ReturnsNoChangeIfNoHash()
{
string source = "x/y.bundle";
string hash = "123abc";
string expected = "x/y.bundle";
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.NoHash, hash, source);
Assert.AreEqual(expected, actual);
}
[Test]
public void GetNameWithHashNaming_CanAppendHash()
{
string source = "x/y.bundle";
string hash = "123abc";
string expected = "x/y_123abc.bundle";
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.AppendHash, hash, source);
Assert.AreEqual(expected, actual);
}
[Test]
public void GetNameWithHashNaming_CanReplaceFileNameWithHash()
{
string source = "x/y.bundle";
string hash = "123abc";
string expected = "123abc.bundle";
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.OnlyHash, hash, source);
Assert.AreEqual(expected, actual);
}
[Test]
public void GetNameWithHashNaming_CanReplaceFileNameWithFileNameHash()
{
string source = "x/y.bundle";
string hash = HashingMethods.Calculate(source).ToString();
string expected = hash + ".bundle";
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.FileNameHash, hash, source);
Assert.AreEqual(expected, actual);
}
// regression test for https://jira.unity3d.com/browse/ADDR-1292
[Test]
public void BuildScriptBaseWriteBuildLog_WhenDirectoryDoesNotExist_DirectoryCreated()
{
string dirName = "SomeTestDir";
string logFile = Path.Combine(dirName, "AddressablesBuildTEP.json");
try
{
BuildLog log = new BuildLog();
BuildScriptBase.WriteBuildLog(log, dirName);
FileAssert.Exists(logFile);
}
finally
{
Directory.Delete(dirName, true);
}
}
[Test]
public void Building_CreatesPerformanceReportWithMetaData()
{
Settings.BuildPlayerContentImpl();
string path = Addressables.LibraryPath + "AddressablesBuildTEP.json";
FileAssert.Exists(path);
string text = File.ReadAllText(path);
StringAssert.Contains("com.unity.addressables", text);
}
[Test]
public void Build_WithInvalidAssetInResourcesFolder_Succeeds()
{
var path = GetAssetPath("Resources/unknownAsset.plist");
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(path)))
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
System.IO.File.WriteAllText(path, "nothing");
AssetDatabase.ImportAsset(path);
var context = new AddressablesDataBuilderInput(Settings);
foreach (IDataBuilder db in Settings.DataBuilders)
if (db.CanBuildData<AddressablesPlayerBuildResult>())
db.BuildData<AddressablesPlayerBuildResult>(context);
}
[Test]
public void Build_GroupWithPlayerDataGroupSchemaAndBundledAssetGroupSchema_LogsError()
{
const string groupName = "NewGroup";
var schemas = new List<AddressableAssetGroupSchema> {ScriptableObject.CreateInstance<PlayerDataGroupSchema>(), ScriptableObject.CreateInstance<BundledAssetGroupSchema>()};
AddressableAssetGroup group = Settings.CreateGroup(groupName, false, false, false, schemas);
var context = new AddressablesDataBuilderInput(Settings);
foreach (IDataBuilder db in Settings.DataBuilders)
{
if (db.CanBuildData<AddressablesPlayerBuildResult>())
{
AddressablesPlayerBuildResult result = db.BuildData<AddressablesPlayerBuildResult>(context);
Assert.AreEqual(result.Error, $"Addressable group {groupName} cannot have both a {typeof(PlayerDataGroupSchema).Name} and a {typeof(BundledAssetGroupSchema).Name}");
}
}
Settings.RemoveGroup(group);
}
// ADDR-1755
[Test]
public void WhenBundleLocalCatalogEnabled_BuildScriptPacked_DoesNotCreatePerformanceLogReport()
{
string logPath = $"Library/com.unity.addressables/aa/{PlatformMappingService.GetPlatformPathSubFolder()}/buildlogtep.json";
if (File.Exists(logPath))
File.Delete(logPath);
Settings.BundleLocalCatalog = true;
var context = new AddressablesDataBuilderInput(Settings);
BuildScriptBase db = (BuildScriptBase)Settings.DataBuilders.Find(x => x.GetType() == typeof(BuildScriptPackedMode));
Assert.IsFalse(File.Exists(logPath)); // make sure file does not exist before build
var res = db.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsFalse(File.Exists(logPath));
}
[Test]
public void Build_WithDeletedAsset_Succeeds()
{
var context = new AddressablesDataBuilderInput(Settings);
//make an entry with no actual AssetPath
Settings.CreateOrMoveEntry("abcde", Settings.DefaultGroup);
Settings.CreateOrMoveEntry(m_AssetGUID, Settings.DefaultGroup);
foreach (BuildScriptBase db in Settings.DataBuilders.OfType<BuildScriptBase>())
{
if (db is BuildScriptPackedPlayMode)
continue;
if (db.CanBuildData<AddressablesPlayerBuildResult>())
{
var res = db.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(db.IsDataBuilt());
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
}
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
{
var res = db.BuildData<AddressablesPlayModeBuildResult>(context);
Assert.IsTrue(db.IsDataBuilt());
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
}
}
Settings.RemoveAssetEntry("abcde", false);
Settings.RemoveAssetEntry(m_AssetGUID, false);
}
[Test]
public void WhenAddressHasSquareBrackets_AndContentCatalogsAreCreated_BuildFails()
{
var context = new AddressablesDataBuilderInput(Settings);
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(m_AssetGUID, Settings.DefaultGroup);
entry.address = "[test]";
LogAssert.Expect(LogType.Error, $"Address '{entry.address}' cannot contain '[ ]'.");
foreach (IDataBuilder db in Settings.DataBuilders)
{
if (db.GetType() == typeof(BuildScriptFastMode) || db.GetType() == typeof(BuildScriptPackedPlayMode))
continue;
if (db.CanBuildData<AddressablesPlayerBuildResult>())
db.BuildData<AddressablesPlayerBuildResult>(context);
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
db.BuildData<AddressablesPlayModeBuildResult>(context);
LogAssert.Expect(LogType.Error, "Address '[test]' cannot contain '[ ]'.");
}
Settings.RemoveAssetEntry(m_AssetGUID, false);
}
[Test]
public void WhenFileTypeIsInvalid_AndContentCatalogsAreCreated_BuildFails()
{
var context = new AddressablesDataBuilderInput(Settings);
string path = GetAssetPath("fake.file");
FileStream fs = File.Create(path);
fs.Close();
AssetDatabase.ImportAsset(path);
string guid = AssetDatabase.AssetPathToGUID(path);
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, Settings.DefaultGroup);
foreach (IDataBuilder db in Settings.DataBuilders)
{
if (db.GetType() == typeof(BuildScriptFastMode) ||
db.GetType() == typeof(BuildScriptPackedPlayMode))
continue;
if (db.CanBuildData<AddressablesPlayerBuildResult>())
db.BuildData<AddressablesPlayerBuildResult>(context);
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
db.BuildData<AddressablesPlayModeBuildResult>(context);
LogAssert.Expect(LogType.Error,
"Cannot recognize file type for entry located at 'Assets/UnityEditor.AddressableAssets.Tests.BuildScriptTests_Tests/fake.file'. Asset import failed for using an unsupported file type.");
}
Settings.RemoveAssetEntry(guid, false);
AssetDatabase.DeleteAsset(path);
}
[Test]
public void WhenFileTypeIsInvalid_AndContentCatalogsAreCreated_IgnoreUnsupportedFilesInBuildIsSet_BuildSucceedWithWarning()
{
bool oldValue = Settings.IgnoreUnsupportedFilesInBuild;
Settings.IgnoreUnsupportedFilesInBuild = true;
var context = new AddressablesDataBuilderInput(Settings);
string path = GetAssetPath("fake.file");
FileStream fs = File.Create(path);
fs.Close();
AssetDatabase.ImportAsset(path);
string guid = AssetDatabase.AssetPathToGUID(path);
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, Settings.DefaultGroup);
foreach (BuildScriptBase db in Settings.DataBuilders.OfType<BuildScriptBase>())
{
if (db.GetType() == typeof(BuildScriptFastMode) || db.GetType() == typeof(BuildScriptPackedPlayMode))
continue;
if (db.CanBuildData<AddressablesPlayerBuildResult>())
{
var res = db.BuildData<AddressablesPlayerBuildResult>(context);
Assert.IsTrue(db.IsDataBuilt());
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
}
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
{
var res = db.BuildData<AddressablesPlayModeBuildResult>(context);
Assert.IsTrue(db.IsDataBuilt());
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
}
LogAssert.Expect(LogType.Warning, new Regex($".*{path}.*ignored"));
LogAssert.Expect(LogType.Warning, new Regex($".*{path}.*stripped"));
}
Settings.RemoveAssetEntry(guid, false);
AssetDatabase.DeleteAsset(path);
Settings.IgnoreUnsupportedFilesInBuild = oldValue;
}
[Test]
public void WhenLoadPathUsesHttp_AndInsecureHttpNotAllowed_BuildLogsWarning()
{
#if UNITY_2022_1_OR_NEWER
InsecureHttpOption oldHttpOption = PlayerSettings.insecureHttpOption;
PlayerSettings.insecureHttpOption = InsecureHttpOption.NotAllowed;
string remoteLoadPathId = Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id;
string oldRemoteLoadPath = Settings.profileSettings.GetValueById(Settings.activeProfileId, remoteLoadPathId);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, "http://insecureconnection/");
AddressableAssetGroup assetGroup = Settings.CreateGroup("InsecureConnections", false, false, false, null, typeof(BundledAssetGroupSchema));
assetGroup.GetSchema<BundledAssetGroupSchema>().BuildPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteBuildPath).Id);
assetGroup.GetSchema<BundledAssetGroupSchema>().LoadPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id);
string assetPath = Path.Combine(TestFolder, "insecureConnectionsTest.prefab");
PrefabUtility.SaveAsPrefabAsset(new GameObject(), assetPath);
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(assetPath), assetGroup, false, false);
var context = new AddressablesDataBuilderInput(Settings);
BuildScriptBase db = (BuildScriptBase)Settings.DataBuilders.Find(x => x.GetType() == typeof(BuildScriptPackedMode));
db.BuildData<AddressablesPlayerBuildResult>(context);
LogAssert.Expect(LogType.Warning, $"Addressable group {assetGroup.Name} uses insecure http for its load path. To allow http connections for UnityWebRequests, change your settings in Edit > Project Settings > Player > Other Settings > Configuration > Allow downloads over HTTP.");
Settings.RemoveGroup(assetGroup);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, oldRemoteLoadPath);
AssetDatabase.DeleteAsset(assetPath);
PlayerSettings.insecureHttpOption = oldHttpOption;
#else
Assert.Ignore($"Skipping test {nameof(WhenLoadPathUsesHttp_AndInsecureHttpNotAllowed_BuildLogsWarning)}.");
#endif
}
[Test]
public void WhenLoadPathUsesHttp_AndInsecureHttpAllowed_BuildSucceeds()
{
#if UNITY_2022_1_OR_NEWER
InsecureHttpOption oldHttpOption = PlayerSettings.insecureHttpOption;
PlayerSettings.insecureHttpOption = InsecureHttpOption.AlwaysAllowed;
string remoteLoadPathId = Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id;
string oldRemoteLoadPath = Settings.profileSettings.GetValueById(Settings.activeProfileId, remoteLoadPathId);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, "http://insecureconnection/");
AddressableAssetGroup assetGroup = Settings.CreateGroup("InsecureConnections", false, false, false, null, typeof(BundledAssetGroupSchema));
assetGroup.GetSchema<BundledAssetGroupSchema>().BuildPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteBuildPath).Id);
assetGroup.GetSchema<BundledAssetGroupSchema>().LoadPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id);
string assetPath = Path.Combine(TestFolder, "insecureConnectionsTest.prefab");
PrefabUtility.SaveAsPrefabAsset(new GameObject(), assetPath);
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(assetPath), assetGroup, false, false);
var context = new AddressablesDataBuilderInput(Settings);
BuildScriptBase db = (BuildScriptBase)Settings.DataBuilders.Find(x => x.GetType() == typeof(BuildScriptPackedMode));
db.BuildData<AddressablesPlayerBuildResult>(context);
LogAssert.NoUnexpectedReceived();
Settings.RemoveGroup(assetGroup);
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, oldRemoteLoadPath);
AssetDatabase.DeleteAsset(assetPath);
PlayerSettings.insecureHttpOption = oldHttpOption;
#else
Assert.Ignore($"Skipping test {nameof(WhenLoadPathUsesHttp_AndInsecureHttpAllowed_BuildSucceeds)}.");
#endif
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e3e97670d537e784e9f104552b533056
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,22 @@
using System;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEngine;
namespace UnityEditor.AddressableAssets.Tests
{
public class BuildScriptVirtualTests : AddressableAssetTestBase
{
[Test]
public void VirtualModeScript_CannotBuildPlayerContent()
{
var buildScript = ScriptableObject.CreateInstance<BuildScriptVirtualMode>();
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
Assert.IsTrue(buildScript.CanBuildData<AddressableAssetBuildResult>());
Assert.IsTrue(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b644b787231a1784ab6bbb39217a63b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,68 @@
using System;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using UnityEngine.TestTools;
namespace UnityEditor.AddressableAssets.Tests
{
public class DataBuilderInputTests : AddressableAssetTestBase
{
[Test]
public void BuildInput_FailsWithNullSettings()
{
var input = new AddressablesDataBuilderInput(null);
LogAssert.Expect(LogType.Error, "Attempting to set up AddressablesDataBuilderInput with null settings.");
Assert.AreEqual(string.Empty, input.PlayerVersion);
input = new AddressablesDataBuilderInput(null, "123");
LogAssert.Expect(LogType.Error, "Attempting to set up AddressablesDataBuilderInput with null settings.");
Assert.AreEqual("123", input.PlayerVersion);
}
[Test]
public void BuildInput_CreatesProperBuildData()
{
var input = new AddressablesDataBuilderInput(Settings);
Assert.AreEqual(EditorUserBuildSettings.activeBuildTarget, input.Target);
Assert.AreEqual(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), input.TargetGroup);
Assert.AreEqual(Settings.PlayerBuildVersion, input.PlayerVersion);
input = new AddressablesDataBuilderInput(Settings, "1234");
Assert.AreEqual(EditorUserBuildSettings.activeBuildTarget, input.Target);
Assert.AreEqual(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), input.TargetGroup);
Assert.AreEqual("1234", input.PlayerVersion);
}
[Test]
public void BuildInput_ReadsProfilerEventState()
{
var oldState = ProjectConfigData.PostProfilerEvents;
ProjectConfigData.PostProfilerEvents = true;
var input = new AddressablesDataBuilderInput(Settings);
Assert.AreEqual(true, input.ProfilerEventsEnabled);
ProjectConfigData.PostProfilerEvents = false;
input = new AddressablesDataBuilderInput(Settings);
Assert.AreEqual(false, input.ProfilerEventsEnabled);
ProjectConfigData.PostProfilerEvents = oldState;
}
[Test]
public void CreateResult_AssignsAllCorrectData()
{
string settingsPath = "Settings/Path";
int locCount = 2;
string error = "Test Error";
var result = AddressableAssetBuildResult.CreateResult<AddressableAssetBuildResult>(settingsPath, locCount, error);
Assert.AreEqual(result.OutputPath, settingsPath);
Assert.AreEqual(result.LocationCount, locCount);
Assert.AreEqual(result.Error, error);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1575d1c3656610c40ad50c15e8f5855a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,314 @@
using NUnit.Framework;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
using UnityEditor.AddressableAssets.Build.DataBuilders;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEditor.Build.Pipeline;
using UnityEngine;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.ResourceProviders;
public class GenerateLocationListsTaskTests : AddressableBuildTaskTestBase
{
GenerateLocationListsTask.Input GenerateDefaultInput()
{
var input = new GenerateLocationListsTask.Input();
input.AssetToFiles = new Dictionary<GUID, List<string>>();
input.FileToBundle = new Dictionary<string, string>();
input.Settings = m_Settings;
input.BundleToAssetGroup = new Dictionary<string, string>();
input.Target = EditorUserBuildSettings.activeBuildTarget;
return input;
}
private bool FindLocationEntry(List<ContentCatalogDataEntry> locations, string key, out ContentCatalogDataEntry entry)
{
foreach (ContentCatalogDataEntry e in locations)
if (e.Keys.Contains(key))
{
entry = e;
return true;
}
entry = null;
return false;
}
static K GetKeyForValue<K, V>(Dictionary<K, V> dict, V value) where V : class
{
foreach (var kvp in dict)
{
if (kvp.Value == value)
return kvp.Key;
}
throw new System.Exception("Couldn't find value");
}
string CreateAddressablePrefab(GenerateLocationListsTask.Input input, string name, AddressableAssetGroup group, params string[] depFiles)
{
string guid = CreateAsset($"{TempPath}/{name}.prefab", name);
var entry = m_Settings.CreateOrMoveEntry(guid, group, false, false);
entry.address = Path.GetFileNameWithoutExtension(entry.AssetPath);
input.AssetToFiles[new GUID(guid)] = new List<string>(depFiles);
return guid;
}
AddressableAssetGroup CreateGroupMappedToBundle(GenerateLocationListsTask.Input input, string postfix)
{
AddressableAssetGroup group = m_Settings.CreateGroup($"testGroup{postfix}", false, false, false, null, typeof(BundledAssetGroupSchema));
input.BundleToAssetGroup[$"bundle{postfix}"] = group.Guid;
input.FileToBundle[$"file{postfix}"] = $"bundle{postfix}";
return group;
}
void AssertLocationDependencies(GenerateLocationListsTask.Output output, string location, params string[] deps)
{
FindLocationEntry(output.Locations, location, out ContentCatalogDataEntry e1);
CollectionAssert.AreEquivalent(e1.Dependencies, deps);
}
static List<AddressableAssetEntry> BuildAddressableAssetEntryList(AddressableAssetSettings settings)
{
List<AddressableAssetEntry> entries = new List<AddressableAssetEntry>();
foreach (AddressableAssetGroup group in settings.groups)
{
group.GatherAllAssets(entries, true, true, false);
}
return entries;
}
[Test]
public void WhenAssetLoadsFromBundle_ProviderTypesIncludesBundledAssetProvider()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
CreateAddressablePrefab(input, "p1", groupX, "fileX");
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
GenerateLocationListsTask.Output output = GenerateLocationListsTask.ProcessInput(input);
CollectionAssert.Contains(output.ProviderTypes, typeof(BundledAssetProvider));
}
[Test]
public void WhenIncludeGUIDInCatalog_SetFalse_GUIDSNotIncluded()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
schema.IncludeGUIDInCatalog = true;
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
if (l.Provider == typeof(BundledAssetProvider).FullName)
CollectionAssert.Contains(l.Keys, guid);
schema.IncludeGUIDInCatalog = false;
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
if (l.Provider == typeof(BundledAssetProvider).FullName)
CollectionAssert.DoesNotContain(l.Keys, guid);
}
[Test]
public void CollectsGuidMapping_WhenCatalogKeysNotIncluded()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
schema.IncludeAddressInCatalog = false;
schema.IncludeGUIDInCatalog = false;
schema.IncludeLabelsInCatalog = false;
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
if (!GUID.TryParse(guid, out GUID g))
Assert.IsFalse(g.Empty());
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
schema.IncludeGUIDInCatalog = true;
var output = GenerateLocationListsTask.ProcessInput(input);
Assert.AreEqual(1, output.GuidToLocation.Count, "Did not gather guid to catalog mapping");
Assert.AreEqual(1, output.GuidToLocation[g].Count);
string path = AssetDatabase.GUIDToAssetPath(guid);
Assert.AreEqual(path, output.GuidToLocation[g][0].InternalId);
}
[Test]
public void WhenIncludeAddressOptionChanged_LocationsKeysAreSetCorrectly()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
schema.IncludeAddressInCatalog = true;
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
if (l.Provider == typeof(BundledAssetProvider).FullName)
CollectionAssert.Contains(l.Keys, "p1");
schema.IncludeAddressInCatalog = false;
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
if (l.Provider == typeof(BundledAssetProvider).FullName)
CollectionAssert.DoesNotContain(l.Keys, "p1");
}
[Test]
public void WhenIncludeLabelsOptionChanged_LocationsKeysAreSetCorrectly()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
groupX.GetAssetEntry(guid).SetLabel("LABEL1", true, true, true);
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
schema.IncludeLabelsInCatalog = true;
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
if (l.Provider == typeof(BundledAssetProvider).FullName)
CollectionAssert.Contains(l.Keys, "LABEL1");
schema.IncludeLabelsInCatalog = false;
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
if (l.Provider == typeof(BundledAssetProvider).FullName)
CollectionAssert.DoesNotContain(l.Keys, "LABEL1");
}
[Test]
public void WhenGroupCreatesMultipleBundles_AllBundlesInAssetGroupToBundlesMap()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup group = m_Settings.CreateGroup($"groupX", false, false, false, null, typeof(BundledAssetGroupSchema));
input.BundleToAssetGroup["bundleX"] = group.Guid;
input.BundleToAssetGroup["bundleY"] = group.Guid;
input.FileToBundle["fileX"] = "bundle1";
input.FileToBundle["fileY"] = "bundle2";
CreateAddressablePrefab(input, "p1", group, "fileX");
CreateAddressablePrefab(input, "p2", group, "fileY");
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
GenerateLocationListsTask.Output output = GenerateLocationListsTask.ProcessInput(input);
CollectionAssert.AreEquivalent(new string[] {"bundle1", "bundle2"}, output.AssetGroupToBundles[group]);
}
[Test]
public void WhenAssetHasDependencyOnBundle_AssetLocationIncludesRecursiveBundleDependencies()
{
GenerateLocationListsTask.Input input = GenerateDefaultInput();
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
AddressableAssetGroup groupY = CreateGroupMappedToBundle(input, "Y");
AddressableAssetGroup groupZ = CreateGroupMappedToBundle(input, "Z");
AddressableAssetGroup groupW = CreateGroupMappedToBundle(input, "W");
CreateAddressablePrefab(input, "p1", groupX, "fileX", "fileY");
CreateAddressablePrefab(input, "p2", groupY, "fileY");
CreateAddressablePrefab(input, "p3", groupY, "fileY", "fileZ");
CreateAddressablePrefab(input, "p4", groupZ, "fileZ");
CreateAddressablePrefab(input, "p5", groupZ, "fileZ", "fileW");
CreateAddressablePrefab(input, "p6", groupW, "fileW");
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
GenerateLocationListsTask.Output output = GenerateLocationListsTask.ProcessInput(input);
AssertLocationDependencies(output, "p1", "bundleX", "bundleY", "bundleZ", "bundleW");
AssertLocationDependencies(output, "p2", "bundleY", "bundleZ", "bundleW");
AssertLocationDependencies(output, "p3", "bundleY", "bundleZ", "bundleW");
AssertLocationDependencies(output, "p4", "bundleZ", "bundleW");
AssertLocationDependencies(output, "p5", "bundleZ", "bundleW");
AssertLocationDependencies(output, "p6", "bundleW");
}
//static
[Test]
[TestCase("abc", BuildTarget.XboxOne, @"\abc")]
[TestCase("abc", BuildTarget.StandaloneWindows64, @"\abc")]
[TestCase("abc", BuildTarget.iOS, @"/abc")]
[TestCase("abc", BuildTarget.Android, @"/abc")]
[TestCase("abc", BuildTarget.StandaloneLinux64, @"/abc")]
[TestCase("abc", BuildTarget.Switch, @"/abc")]
[TestCase("abc", BuildTarget.StandaloneOSX, @"/abc")]
public void WhenBuildTargetIsWindowsOrXBox_BackSlashUsedInLoadPath(string id, BuildTarget target, string expected)
{
AddressableAssetGroup group = m_Settings.CreateGroup($"xyz", false, false, false, null, typeof(BundledAssetGroupSchema));
var bag = group.GetSchema<BundledAssetGroupSchema>();
var expectedPath = $"{bag.LoadPath.GetValue(m_Settings)}{expected}".Replace('/', GenerateLocationListsTask.PathSeparatorForPlatform(target));
var path = GenerateLocationListsTask.GetLoadPath(group, id, target);
Assert.AreEqual(expectedPath, path);
m_Settings.RemoveGroup(group);
}
[Test]
[TestCase("abc", BuildTarget.XboxOne)]
[TestCase("abc", BuildTarget.StandaloneWindows64)]
[TestCase("abc", BuildTarget.iOS)]
[TestCase("abc", BuildTarget.Android)]
[TestCase("abc", BuildTarget.StandaloneLinux64)]
[TestCase("abc", BuildTarget.Switch)]
[TestCase("abc", BuildTarget.StandaloneOSX)]
public void WhenPathIsRemote_WithTrailingSlash_PathIsNotMalformed(string id, BuildTarget target)
{
//Setup
string baseId = m_Settings.profileSettings.Reset();
string profileId = m_Settings.profileSettings.AddProfile("remote", baseId);
m_Settings.profileSettings.SetValue(profileId, AddressableAssetSettings.kRemoteLoadPath, "http://127.0.0.1:80/");
m_Settings.activeProfileId = profileId;
AddressableAssetGroup group = m_Settings.CreateGroup($"xyz", false, false, false, null, typeof(BundledAssetGroupSchema));
var bag = group.GetSchema<BundledAssetGroupSchema>();
bag.LoadPath.Id = m_Settings.profileSettings.GetVariableId(AddressableAssetSettings.kRemoteLoadPath);
//Test
var path = GenerateLocationListsTask.GetLoadPath(group, id, target);
string pahWithoutHttp = path.Replace("http://", "");
//Assert
Assert.IsFalse(path.Contains("/\\"));
Assert.IsFalse(pahWithoutHttp.Contains("//"));
//Cleanup
m_Settings.RemoveGroup(group);
m_Settings.activeProfileId = baseId;
}
[Test]
[TestCase("abc", BuildTarget.XboxOne)]
[TestCase("abc", BuildTarget.StandaloneWindows64)]
[TestCase("abc", BuildTarget.iOS)]
[TestCase("abc", BuildTarget.Android)]
[TestCase("abc", BuildTarget.StandaloneLinux64)]
[TestCase("abc", BuildTarget.Switch)]
[TestCase("abc", BuildTarget.StandaloneOSX)]
public void WhenPathIsRemote_WithoutTrailingSlash_PathIsNotMalformed(string id, BuildTarget target)
{
//Setup
string baseId = m_Settings.profileSettings.Reset();
string profileId = m_Settings.profileSettings.AddProfile("remote", baseId);
m_Settings.profileSettings.SetValue(profileId, AddressableAssetSettings.kRemoteLoadPath, "http://127.0.0.1:80");
m_Settings.activeProfileId = profileId;
AddressableAssetGroup group = m_Settings.CreateGroup($"xyz", false, false, false, null, typeof(BundledAssetGroupSchema));
var bag = group.GetSchema<BundledAssetGroupSchema>();
bag.LoadPath.Id = m_Settings.profileSettings.GetVariableId(AddressableAssetSettings.kRemoteLoadPath);
//Test
var path = GenerateLocationListsTask.GetLoadPath(group, id, target);
string pahWithoutHttp = path.Replace("http://", "");
//Assert
Assert.IsFalse(path.Contains("/\\"));
Assert.IsFalse(pahWithoutHttp.Contains("//"));
//Cleanup
m_Settings.RemoveGroup(group);
m_Settings.activeProfileId = baseId;
}
//[Test]
//public void WhenEntryAddressContainsBrackets_ExceptionIsThrown()
//{
// TODO:
//}
//}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28e27e70c0f8cee45a62f86887957a0f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: