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);
 | |
|         }
 | |
|     }
 | |
| }
 |