A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using System.IO; 4using System.Linq; 5using UnityEditor.TestTools.TestRunner.Api; 6using UnityEngine; 7using UnityEngine.TestRunner.NUnitExtensions.Runner; 8 9namespace UnityEditor.TestTools.TestRunner 10{ 11 /// <summary> 12 /// Handles deserialization of TestSettings from a provided json file path. 13 /// </summary> 14 internal class TestSettingsDeserializer : ITestSettingsDeserializer 15 { 16 private static readonly SettingsMap[] s_SettingsMapping = 17 { 18 new SettingsMap<ScriptingImplementation>("scriptingBackend", (settings, value) => settings.scriptingBackend = value), 19 new SettingsMap<string>("architecture", (settings, value) => settings.Architecture = value), 20 new SettingsMap<ApiCompatibilityLevel>("apiProfile", (settings, value) => settings.apiProfile = value), 21 new SettingsMap<bool>("appleEnableAutomaticSigning", (settings, value) => settings.appleEnableAutomaticSigning = value), 22 new SettingsMap<string>("appleDeveloperTeamID", (settings, value) => settings.appleDeveloperTeamID = value), 23 new SettingsMap<ProvisioningProfileType>("iOSManualProvisioningProfileType", (settings, value) => settings.iOSManualProvisioningProfileType = value), 24 new SettingsMap<string>("iOSManualProvisioningProfileID", (settings, value) => settings.iOSManualProvisioningProfileID = value), 25 new SettingsMap<string>("iOSTargetSDK", (settings, value) => settings.iOSTargetSDK = value), 26 new SettingsMap<ProvisioningProfileType>("tvOSManualProvisioningProfileType", (settings, value) => settings.tvOSManualProvisioningProfileType = value), 27 new SettingsMap<string>("tvOSManualProvisioningProfileID", (settings, value) => settings.tvOSManualProvisioningProfileID = value), 28 new SettingsMap<string>("tvOSTargetSDK", (settings, value) => settings.tvOSTargetSDK = value), 29 new SettingsMap<string>("playerGraphicsAPI", (settings, value) => 30 { 31 settings.autoGraphicsAPIs = false; 32 settings.playerGraphicsAPIs = new[] {value}; 33 }), 34 new SettingsMap<bool>("androidBuildAppBundle", (settings, value) => 35 { 36 settings.androidBuildAppBundle = value; 37 }), 38 new SettingsMap<List<object>>("ignoreTests", (settings, list) => 39 { 40 settings.ignoreTests = list.Select(item => 41 { 42 var dictionary = (Dictionary<string, object>)item; 43 if (dictionary.ContainsKey("test") && dictionary.ContainsKey("ignoreComment")) 44 { 45 return new IgnoreTest() 46 { 47 test = dictionary["test"] as string, 48 ignoreComment = dictionary["ignoreComment"] as string 49 }; 50 } 51 52 throw new Exception("Wrong format for ignore test. Expected \"test\" and \"ignoreComment\"."); 53 }).ToArray(); 54 }), 55 new SettingsMap<Dictionary<string, object>>("featureFlags", (settings, dictionary) => 56 { 57 var converted = dictionary.ToDictionary(pair => pair.Key, pair => (bool)pair.Value); 58 var featureFlags = new FeatureFlags(); 59 if (converted.ContainsKey("fileCleanUpCheck")) 60 { 61 featureFlags.fileCleanUpCheck = converted["fileCleanUpCheck"]; 62 } 63 if (converted.ContainsKey("strictDomainReload")) 64 { 65 featureFlags.strictDomainReload = converted["strictDomainReload"]; 66 } 67 if (converted.ContainsKey("requiresSplashScreen")) 68 { 69 featureFlags.requiresSplashScreen = converted["requiresSplashScreen"]; 70 } 71 if (converted.ContainsKey("disableNestedEnumeratorBugfix")) 72 { 73 featureFlags.disableNestedEnumeratorBugfix = converted["disableNestedEnumeratorBugfix"]; 74 } 75 76 settings.featureFlags = featureFlags; 77 }), 78#if UNITY_2023_2_OR_NEWER 79 new SettingsMap<WebGLClientBrowserType>("webGLClientBrowserType", (settings, value) => settings.webGLClientBrowserType = value), 80 new SettingsMap<string>("webGLClientBrowserPath", (settings, value) => settings.webGLClientBrowserPath = value), 81#endif 82 }; 83 84 private readonly Func<ITestSettings> m_TestSettingsFactory; 85 public TestSettingsDeserializer(Func<ITestSettings> testSettingsFactory) 86 { 87 m_TestSettingsFactory = testSettingsFactory; 88 } 89 90 public ITestSettings GetSettingsFromJsonFile(string jsonFilePath) 91 { 92 var text = File.ReadAllText(jsonFilePath); 93 var settingsDictionary = Json.Deserialize(text) as Dictionary<string, object>; 94 95 var testSettings = m_TestSettingsFactory(); 96 if (settingsDictionary == null) 97 { 98 return testSettings; 99 } 100 101 foreach (var settingsMap in s_SettingsMapping) 102 { 103 if (!settingsDictionary.ContainsKey(settingsMap.Key)) 104 { 105 continue; 106 } 107 108 if (settingsMap.Type.IsEnum) 109 { 110 SetEnumValue(settingsMap.Key, settingsDictionary[settingsMap.Key], settingsMap.Type, value => settingsMap.ApplyToSettings(testSettings, value)); 111 } 112 else 113 { 114 SetValue(settingsMap.Key, settingsDictionary[settingsMap.Key], settingsMap.Type, value => settingsMap.ApplyToSettings(testSettings, value)); 115 } 116 } 117 118 return testSettings; 119 } 120 121 private abstract class SettingsMap 122 { 123 public string Key { get; } 124 public Type Type { get; } 125 protected SettingsMap(string key, Type type) 126 { 127 Key = key; 128 Type = type; 129 } 130 131 public abstract void ApplyToSettings(ITestSettings settings, object value); 132 } 133 134 private class SettingsMap<T> : SettingsMap 135 { 136 private Action<ITestSettings, T> m_Setter; 137 public SettingsMap(string key, Action<ITestSettings, T> setter) : base(key, typeof(T)) 138 { 139 m_Setter = setter; 140 } 141 142 public override void ApplyToSettings(ITestSettings settings, object value) 143 { 144 m_Setter(settings, (T)value); 145 } 146 } 147 148 private static void SetEnumValue(string key, object value, Type type, Action<object> setter) 149 { 150 object enumValue; 151 if (TryGetEnum(value as string, type, out enumValue)) 152 { 153 setter(enumValue); 154 return; 155 } 156 157 var acceptedValues = string.Join(", ", Enum.GetValues(type).OfType<object>().Select(val => val.ToString()).ToArray()); 158 159 Debug.LogFormat("Could not convert '{0}' argument '{1}' to a valid {2}. Accepted values: {3}.", key, value, type.Name, acceptedValues); 160 } 161 162 private static bool TryGetEnum(string value, Type type, out object enumValue) 163 { 164 try 165 { 166 enumValue = Enum.Parse(type, value, true); 167 return true; 168 } 169 catch (Exception) 170 { 171 enumValue = null; 172 return false; 173 } 174 } 175 176 private static void SetValue(string key, object value, Type type, Action<object> setter) 177 { 178 if (type.IsInstanceOfType(value)) 179 { 180 setter(value); 181 return; 182 } 183 184 Debug.LogFormat("Could not convert '{0}' argument '{1}' to a valid {2}.", key, value, type.Name); 185 } 186 } 187}