using NUnit.Framework; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using UnityEngine.Rendering; namespace RenderPipelineGraphicsSettings { [TestFixture] class StripperTests { #region Strippers static HashSet s_EnabledStrippers = new(); private struct ActiveStrippersScope : IDisposable { private readonly List m_Fields; public ActiveStrippersScope(List activeStrippers) { m_Fields = new List(); foreach (var stripper in activeStrippers) { var field = stripper.GetField("k_Invoked", BindingFlags.Static | BindingFlags.Public); if (field != null) { field.SetValue(null, false); m_Fields.Add(field); s_EnabledStrippers.Add(stripper); } } } public void Dispose() { foreach (var field in m_Fields) { Assert.IsTrue((bool)field.GetValue(null), "CanRemoveSettings was not invoked"); } m_Fields.Clear(); s_EnabledStrippers.Clear(); } } class RemoveAStripper : IRenderPipelineGraphicsSettingsStripper { public static bool k_Invoked = false; public bool active => s_EnabledStrippers.Contains(typeof(RemoveAStripper)); public bool CanRemoveSettings(A setting) { k_Invoked = true; return true; } } class KeepAStripper : IRenderPipelineGraphicsSettingsStripper { public static bool k_Invoked = false; public bool active => s_EnabledStrippers.Contains(typeof(KeepAStripper)); public bool CanRemoveSettings(A setting) { k_Invoked = true; return false; } } class PrivateCtorAStripper : IRenderPipelineGraphicsSettingsStripper { public bool active => s_EnabledStrippers.Contains(typeof(PrivateCtorAStripper)); private PrivateCtorAStripper() { } public bool CanRemoveSettings(A setting) { return true; } } class WrongStripper : IStripper { public bool active => s_EnabledStrippers.Contains(typeof(PrivateCtorAStripper)); } #endregion #region SettingsDefinitions class StripperTestsAsset : RenderPipelineAsset { protected override RenderPipeline CreatePipeline() { throw new NotImplementedException(); } } [Serializable] [SupportedOnRenderPipeline(typeof(StripperTestsAsset))] public abstract class Base : IRenderPipelineGraphicsSettings { int IRenderPipelineGraphicsSettings.version => 0; public string name; public Base() => name = GetType().Name; public override string ToString() => name; public virtual bool isAvailableInPlayerBuild => false; } [Serializable] class A : Base { public override bool isAvailableInPlayerBuild => true; } [Serializable] class B : Base { public override bool isAvailableInPlayerBuild => true; } [Serializable] class C : Base { } #endregion private static A k_A = new A(); private static B k_B = new B(); private static C k_C = new C(); static string k_ResultsDirectory = "Packages/com.unity.render-pipelines.core/Tests/Editor/RenderPipeline/SettingsStrippingResults"; [SetUp] public void Setup() { if (k_UpdateStrippingResult && !Directory.Exists(k_ResultsDirectory)) Directory.CreateDirectory(k_ResultsDirectory); } static TestCaseData[] s_TestCaseDatas = { new TestCaseData( new List(), new List()) .SetName("Given no settings and no strippers, nothing is performed") .Returns(new List()), new TestCaseData( new List() { k_A, k_B, k_C }, new List()) .SetName( "Given some settings without any stripper active, only settings that must be available on Player build are kept") .Returns(new List() { k_A, k_B }), new TestCaseData( new List() { k_A, k_B, k_C }, new List() { typeof(WrongStripper) }) .SetName("Given an wrong stripper, the stripper is not taken into account.") .Returns(new List() { k_A, k_B }), new TestCaseData( new List() { k_A, k_B, k_C }, new List() { typeof(PrivateCtorAStripper) }) .SetName("Given an user stripper with private constructor, the stripper is not taken into account.") .Returns(new List() { k_A, k_B }), new TestCaseData( new List() { k_A, k_B, k_C }, new List() { typeof(RemoveAStripper) }) .SetName("Given an user stripper, the default behaviour of the setting is overriden") .Returns(new List() { k_B }), new TestCaseData( new List() { k_A, k_B, k_C }, new List() { typeof(KeepAStripper), typeof(RemoveAStripper) }) .SetName("Given a settings keeper and a settings stripper, the setting is kept") .Returns(new List() { k_A, k_B }) }; [Test, TestCaseSource(nameof(s_TestCaseDatas))] public List DoStripping(List settings, List activeStrippers) { using (new ActiveStrippersScope(activeStrippers)) { var runtimeSettings = new List(); RenderPipelineGraphicsSettingsStripper.PerformStripping(settings, runtimeSettings); return runtimeSettings; } } static bool k_UpdateStrippingResult = false; private void CheckForceUpdate(string path, string loggedStrippedResult) { if (k_UpdateStrippingResult) { if (File.Exists(path)) File.Delete(path); File.WriteAllText(path, loggedStrippedResult); } Assert.IsFalse(k_UpdateStrippingResult, "Note to Developer: You forgot to set back the variable `k_UpdateStrippingResult` to false"); } private string GenerateFilePath(List settings, List activeStrippers) { string activeStrippersFilePath = activeStrippers.Count != 0 ? string.Join('_', activeStrippers.Select(i => i.Name)) : "no_strippers_active"; string settingsFilePath = settings.Count != 0 ? string.Join('_', settings.Select(i => i.GetType().Name)) : "no_settings"; return Path.GetFullPath(Path.Combine(k_ResultsDirectory, $"{activeStrippersFilePath}_{settingsFilePath}.json")); } [Test, TestCaseSource(nameof(s_TestCaseDatas))] public List JSONOutput(List settings, List activeStrippers) { var runtimeSettings = DoStripping(settings, activeStrippers); string path = GenerateFilePath(settings, activeStrippers); var loggedStrippedResult = File.ReadAllText(RenderPipelineGraphicsSettingsStripper.Report.k_OutputPath); CheckForceUpdate(path, loggedStrippedResult); Assert.AreEqual(File.ReadAllText(path), loggedStrippedResult, "Note to Developer: You can set the variable `k_UpdateStrippingResult` to true, to override the output if you changed what is reported"); return runtimeSettings; } [Test] public void NullArgumentsThrowsException() { var initializedList = new List(); var exception = Assert.Throws(() =>RenderPipelineGraphicsSettingsStripper.PerformStripping(null, initializedList)); Assert.AreEqual("settingsList", exception.ParamName); exception = Assert.Throws(() => RenderPipelineGraphicsSettingsStripper.PerformStripping(initializedList, null)); Assert.AreEqual("runtimeSettingsList", exception.ParamName); } } }