188 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			188 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using System.IO; | ||
|  | using System.Linq; | ||
|  | using UnityEditor.TestTools.TestRunner.Api; | ||
|  | using UnityEngine; | ||
|  | using UnityEngine.TestRunner.NUnitExtensions.Runner; | ||
|  | 
 | ||
|  | namespace UnityEditor.TestTools.TestRunner | ||
|  | { | ||
|  |     /// <summary> | ||
|  |     /// Handles deserialization of TestSettings from a provided json file path. | ||
|  |     /// </summary> | ||
|  |     internal class TestSettingsDeserializer : ITestSettingsDeserializer | ||
|  |     { | ||
|  |         private static readonly SettingsMap[] s_SettingsMapping = | ||
|  |         { | ||
|  |             new SettingsMap<ScriptingImplementation>("scriptingBackend", (settings, value) => settings.scriptingBackend = value), | ||
|  |             new SettingsMap<string>("architecture", (settings, value) => settings.Architecture = value), | ||
|  |             new SettingsMap<ApiCompatibilityLevel>("apiProfile", (settings, value) => settings.apiProfile = value), | ||
|  |             new SettingsMap<bool>("appleEnableAutomaticSigning", (settings, value) => settings.appleEnableAutomaticSigning = value), | ||
|  |             new SettingsMap<string>("appleDeveloperTeamID", (settings, value) => settings.appleDeveloperTeamID = value), | ||
|  |             new SettingsMap<ProvisioningProfileType>("iOSManualProvisioningProfileType", (settings, value) => settings.iOSManualProvisioningProfileType = value), | ||
|  |             new SettingsMap<string>("iOSManualProvisioningProfileID", (settings, value) => settings.iOSManualProvisioningProfileID = value), | ||
|  |             new SettingsMap<string>("iOSTargetSDK", (settings, value) => settings.iOSTargetSDK = value), | ||
|  |             new SettingsMap<ProvisioningProfileType>("tvOSManualProvisioningProfileType", (settings, value) => settings.tvOSManualProvisioningProfileType = value), | ||
|  |             new SettingsMap<string>("tvOSManualProvisioningProfileID", (settings, value) => settings.tvOSManualProvisioningProfileID = value), | ||
|  |             new SettingsMap<string>("tvOSTargetSDK", (settings, value) => settings.tvOSTargetSDK = value), | ||
|  |             new SettingsMap<string>("playerGraphicsAPI", (settings, value) => | ||
|  |             { | ||
|  |                 settings.autoGraphicsAPIs = false; | ||
|  |                 settings.playerGraphicsAPIs = new[] {value}; | ||
|  |             }), | ||
|  |             new SettingsMap<bool>("androidBuildAppBundle", (settings, value) => | ||
|  |             { | ||
|  |                 settings.androidBuildAppBundle = value; | ||
|  |             }), | ||
|  |             new SettingsMap<List<object>>("ignoreTests", (settings, list) => | ||
|  |             { | ||
|  |                 settings.ignoreTests = list.Select(item => | ||
|  |                 { | ||
|  |                     var dictionary = (Dictionary<string, object>)item; | ||
|  |                     if (dictionary.ContainsKey("test") && dictionary.ContainsKey("ignoreComment")) | ||
|  |                     { | ||
|  |                         return new IgnoreTest() | ||
|  |                         { | ||
|  |                             test = dictionary["test"] as string, | ||
|  |                             ignoreComment = dictionary["ignoreComment"] as string | ||
|  |                         }; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     throw new Exception("Wrong format for ignore test. Expected \"test\" and \"ignoreComment\"."); | ||
|  |                 }).ToArray(); | ||
|  |             }), | ||
|  |             new SettingsMap<Dictionary<string, object>>("featureFlags", (settings, dictionary) => | ||
|  |             { | ||
|  |                 var converted = dictionary.ToDictionary(pair => pair.Key, pair => (bool)pair.Value); | ||
|  |                 var featureFlags = new FeatureFlags(); | ||
|  |                 if (converted.ContainsKey("fileCleanUpCheck")) | ||
|  |                 { | ||
|  |                     featureFlags.fileCleanUpCheck = converted["fileCleanUpCheck"]; | ||
|  |                 } | ||
|  |                 if (converted.ContainsKey("strictDomainReload")) | ||
|  |                 { | ||
|  |                     featureFlags.strictDomainReload = converted["strictDomainReload"]; | ||
|  |                 } | ||
|  |                 if (converted.ContainsKey("requiresSplashScreen")) | ||
|  |                 { | ||
|  |                     featureFlags.requiresSplashScreen = converted["requiresSplashScreen"]; | ||
|  |                 } | ||
|  |                 if (converted.ContainsKey("disableNestedEnumeratorBugfix")) | ||
|  |                 { | ||
|  |                     featureFlags.disableNestedEnumeratorBugfix = converted["disableNestedEnumeratorBugfix"]; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 settings.featureFlags = featureFlags; | ||
|  |             }), | ||
|  | #if UNITY_2023_2_OR_NEWER | ||
|  |             new SettingsMap<WebGLClientBrowserType>("webGLClientBrowserType", (settings, value) => settings.webGLClientBrowserType = value), | ||
|  |             new SettingsMap<string>("webGLClientBrowserPath", (settings, value) => settings.webGLClientBrowserPath = value), | ||
|  | #endif | ||
|  |         }; | ||
|  | 
 | ||
|  |         private readonly Func<ITestSettings> m_TestSettingsFactory; | ||
|  |         public TestSettingsDeserializer(Func<ITestSettings> testSettingsFactory) | ||
|  |         { | ||
|  |             m_TestSettingsFactory = testSettingsFactory; | ||
|  |         } | ||
|  | 
 | ||
|  |         public ITestSettings GetSettingsFromJsonFile(string jsonFilePath) | ||
|  |         { | ||
|  |             var text = File.ReadAllText(jsonFilePath); | ||
|  |             var settingsDictionary = Json.Deserialize(text) as Dictionary<string, object>; | ||
|  | 
 | ||
|  |             var testSettings = m_TestSettingsFactory(); | ||
|  |             if (settingsDictionary == null) | ||
|  |             { | ||
|  |                 return testSettings; | ||
|  |             } | ||
|  | 
 | ||
|  |             foreach (var settingsMap in s_SettingsMapping) | ||
|  |             { | ||
|  |                 if (!settingsDictionary.ContainsKey(settingsMap.Key)) | ||
|  |                 { | ||
|  |                     continue; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (settingsMap.Type.IsEnum) | ||
|  |                 { | ||
|  |                     SetEnumValue(settingsMap.Key, settingsDictionary[settingsMap.Key], settingsMap.Type, value => settingsMap.ApplyToSettings(testSettings, value)); | ||
|  |                 } | ||
|  |                 else | ||
|  |                 { | ||
|  |                     SetValue(settingsMap.Key, settingsDictionary[settingsMap.Key], settingsMap.Type, value => settingsMap.ApplyToSettings(testSettings, value)); | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             return testSettings; | ||
|  |         } | ||
|  | 
 | ||
|  |         private abstract class SettingsMap | ||
|  |         { | ||
|  |             public string Key { get; } | ||
|  |             public Type Type { get; } | ||
|  |             protected SettingsMap(string key, Type type) | ||
|  |             { | ||
|  |                 Key = key; | ||
|  |                 Type = type; | ||
|  |             } | ||
|  | 
 | ||
|  |             public abstract void ApplyToSettings(ITestSettings settings, object value); | ||
|  |         } | ||
|  | 
 | ||
|  |         private class SettingsMap<T> : SettingsMap | ||
|  |         { | ||
|  |             private Action<ITestSettings, T> m_Setter; | ||
|  |             public SettingsMap(string key, Action<ITestSettings, T> setter) : base(key, typeof(T)) | ||
|  |             { | ||
|  |                 m_Setter = setter; | ||
|  |             } | ||
|  | 
 | ||
|  |             public override void ApplyToSettings(ITestSettings settings, object value) | ||
|  |             { | ||
|  |                 m_Setter(settings, (T)value); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         private static void SetEnumValue(string key, object value, Type type, Action<object> setter) | ||
|  |         { | ||
|  |             object enumValue; | ||
|  |             if (TryGetEnum(value as string, type, out enumValue)) | ||
|  |             { | ||
|  |                 setter(enumValue); | ||
|  |                 return; | ||
|  |             } | ||
|  | 
 | ||
|  |             var acceptedValues = string.Join(", ", Enum.GetValues(type).OfType<object>().Select(val => val.ToString()).ToArray()); | ||
|  | 
 | ||
|  |             Debug.LogFormat("Could not convert '{0}' argument '{1}' to a valid {2}. Accepted values: {3}.", key, value, type.Name, acceptedValues); | ||
|  |         } | ||
|  | 
 | ||
|  |         private static bool TryGetEnum(string value, Type type, out object enumValue) | ||
|  |         { | ||
|  |             try | ||
|  |             { | ||
|  |                 enumValue = Enum.Parse(type, value, true); | ||
|  |                 return true; | ||
|  |             } | ||
|  |             catch (Exception) | ||
|  |             { | ||
|  |                 enumValue = null; | ||
|  |                 return false; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         private static void SetValue(string key, object value, Type type, Action<object> setter) | ||
|  |         { | ||
|  |             if (type.IsInstanceOfType(value)) | ||
|  |             { | ||
|  |                 setter(value); | ||
|  |                 return; | ||
|  |             } | ||
|  | 
 | ||
|  |             Debug.LogFormat("Could not convert '{0}' argument '{1}' to a valid {2}.", key, value, type.Name); | ||
|  |         } | ||
|  |     } | ||
|  | } |