Newer
Older
HoloAnatomy / Assets / HoloToolkit-UnitTests / Editor / Utilities / TestUtils.cs
SURFACEBOOK2\jackwynne on 25 May 2018 5 KB v1
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace HoloToolkit.Unity
{
    public static class TestUtils
    {
        /// <summary>
        /// Deletes all objects in the scene
        /// </summary>
        public static void ClearScene()
        {
            ClearUnreferencedActive();
            ClearUnreferencedDisabledInTestScene();
        }

        private static void ClearUnreferencedDisabledInTestScene()
        {
            DestroyGameObjects(SceneManager.GetActiveScene().GetRootGameObjects());
        }

        private static void ClearUnreferencedActive()
        {
            DestroyTransforms(Object.FindObjectsOfType<Transform>());
        }

        private static void DestroyTransforms(IEnumerable<Transform> transforms)
        {
            DestroyGameObjects(transforms.Where(t => t).Select(t => t.root.gameObject).Distinct());
        }

        private static void DestroyGameObjects(IEnumerable<GameObject> gameObjects)
        {
            foreach (var gameObject in gameObjects)
            {
                Object.DestroyImmediate(gameObject);
            }
        }

        /// <summary>
        /// Creates a camera and adds the MainCamera tag to it
        /// </summary>
        /// <returns>The created camera</returns>
        public static Camera CreateMainCamera()
        {
            var camera = new GameObject().AddComponent<Camera>();
            camera.gameObject.tag = "MainCamera";
            return camera;
        }

        /// <summary>
        /// Calls Awake, OnEnable and Start on all MonoBehaviours on the given gameObject through reflection.
        /// </summary>
        /// <param name="gameObject">The gameObject to be initialized</param>
        /// <returns>The given gameObject to be able to chain call</returns>
        internal static GameObject CallInitialization(this GameObject gameObject)
        {
            return gameObject.CallAwake().CallOnEnable().CallStart();
        }

        /// <summary>
        /// Calls Awake on all MonoBehaviours on the given gameObject through reflection.
        /// </summary>
        /// <param name="gameObject">The gameObject to be awoken</param>
        /// <returns>The given gameObject to be able to chain call</returns>
        internal static GameObject CallAwake(this GameObject gameObject)
        {
            return gameObject.CallAllMonoBehaviours("Awake");
        }

        /// <summary>
        /// Calls OnEnable on all MonoBehaviours on the given gameObject through reflection.
        /// </summary>
        /// <param name="gameObject">The gameObject to be enabled</param>
        /// <returns>The given gameObject to be able to chain call</returns>
        internal static GameObject CallOnEnable(this GameObject gameObject)
        {
            return gameObject.CallAllMonoBehaviours("OnEnable");
        }

        /// <summary>
        /// Calls Start on all MonoBehaviours on the given gameObject through reflection.
        /// </summary>
        /// <param name="gameObject">The gameObject to be started</param>
        /// <returns>The given gameObject to be able to chain call</returns>
        internal static GameObject CallStart(this GameObject gameObject)
        {
            return gameObject.CallAllMonoBehaviours("Start");
        }

        /// <summary>
        /// Calls Update on all MonoBehaviours on the given gameObject through reflection.
        /// </summary>
        /// <param name="gameObject">The gameObject to be updated</param>
        /// <returns>The given gameObject to be able to chain call</returns>
        internal static GameObject CallUpdate(this GameObject gameObject)
        {
            return gameObject.CallAllMonoBehaviours("Update");
        }


        /// <summary>
        /// Calls the given method on all MonoBehaviours on the given gameObject through reflection.
        /// </summary>
        /// <param name="gameObject">The gameObject that contains the monoBehaviour</param>
        /// <param name="methodName">The method to call</param>
        /// <returns>The given gameObject to be able to chain call</returns>
        internal static GameObject CallAllMonoBehaviours(this GameObject gameObject, string methodName)
        {
            foreach (var script in gameObject.GetComponentsInChildren<MonoBehaviour>())
            {
                script.Call(methodName);
            }
            return gameObject;
        }

        /// <summary>
        /// Call a method with the given name from the given object through reflection
        /// </summary>
        /// <param name="obj">Object to call the method on</param>
        /// <param name="methodName">The method that should be called</param>
        private static void Call(this object obj, string methodName)
        {
            const BindingFlags findFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            var methodInfo = obj.GetType().GetMethod(methodName, findFlags);
            if (methodInfo == null) return;
            methodInfo.Invoke(obj, null);
        }
    }
}