using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; namespace UnityEditor.TestTools.TestRunner { /// /// Handles deserialization of TestSettings from a provided json file path. /// internal class TestSettingsDeserializer : ITestSettingsDeserializer { private static readonly SettingsMap[] s_SettingsMapping = { new SettingsMap("scriptingBackend", (settings, value) => settings.scriptingBackend = value), new SettingsMap("architecture", (settings, value) => settings.Architecture = value), new SettingsMap("apiProfile", (settings, value) => settings.apiProfile = value), new SettingsMap("appleEnableAutomaticSigning", (settings, value) => settings.appleEnableAutomaticSigning = value), new SettingsMap("appleDeveloperTeamID", (settings, value) => settings.appleDeveloperTeamID = value), new SettingsMap("iOSManualProvisioningProfileType", (settings, value) => settings.iOSManualProvisioningProfileType = value), new SettingsMap("iOSManualProvisioningProfileID", (settings, value) => settings.iOSManualProvisioningProfileID = value), new SettingsMap("tvOSManualProvisioningProfileType", (settings, value) => settings.tvOSManualProvisioningProfileType = value), new SettingsMap("tvOSManualProvisioningProfileID", (settings, value) => settings.tvOSManualProvisioningProfileID = value), new SettingsMap("playerGraphicsAPI", (settings, value) => { settings.autoGraphicsAPIs = false; settings.playerGraphicsAPIs = new[] {value}; }), new SettingsMap("androidBuildAppBundle", (settings, value) => { settings.androidBuildAppBundle = value; }) }; private readonly Func m_TestSettingsFactory; public TestSettingsDeserializer(Func testSettingsFactory) { m_TestSettingsFactory = testSettingsFactory; } public ITestSettings GetSettingsFromJsonFile(string jsonFilePath) { var text = File.ReadAllText(jsonFilePath); var settingsDictionary = Json.Deserialize(text) as Dictionary; 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 : SettingsMap { private Action m_Setter; public SettingsMap(string key, Action 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 setter) { object enumValue; if (TryGetEnum(value as string, type, out enumValue)) { setter(enumValue); return; } var acceptedValues = string.Join(", ", Enum.GetValues(type).OfType().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 setter) { if (type.IsInstanceOfType(value)) { setter(value); return; } Debug.LogFormat("Could not convert '{0}' argument '{1}' to a valid {2}.", key, value, type.Name); } } }