PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Assets/UnityTestTools/Assertions/AssertionComponent.cs

https://gitlab.com/wizcas/Unity-GitLab-CI-Test
C# | 379 lines | 371 code | 8 blank | 0 comment | 2 complexity | a8c9e6e5f7c4efd7c2ef00979b7af717 MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using UnityEngine;
  7. using Debug = UnityEngine.Debug;
  8. using Object = UnityEngine.Object;
  9. namespace UnityTest
  10. {
  11. [Serializable]
  12. public class AssertionComponent : MonoBehaviour, IAssertionComponentConfigurator
  13. {
  14. [SerializeField] public float checkAfterTime = 1f;
  15. [SerializeField] public bool repeatCheckTime = true;
  16. [SerializeField] public float repeatEveryTime = 1f;
  17. [SerializeField] public int checkAfterFrames = 1;
  18. [SerializeField] public bool repeatCheckFrame = true;
  19. [SerializeField] public int repeatEveryFrame = 1;
  20. [SerializeField] public bool hasFailed;
  21. [SerializeField] public CheckMethod checkMethods = CheckMethod.Start;
  22. [SerializeField] private ActionBase m_ActionBase;
  23. [SerializeField] public int checksPerformed = 0;
  24. private int m_CheckOnFrame;
  25. private string m_CreatedInFilePath = "";
  26. private int m_CreatedInFileLine = -1;
  27. public ActionBase Action
  28. {
  29. get { return m_ActionBase; }
  30. set
  31. {
  32. m_ActionBase = value;
  33. m_ActionBase.go = gameObject;
  34. }
  35. }
  36. public Object GetFailureReferenceObject()
  37. {
  38. #if UNITY_EDITOR
  39. if (!string.IsNullOrEmpty(m_CreatedInFilePath))
  40. {
  41. return UnityEditor.AssetDatabase.LoadAssetAtPath(m_CreatedInFilePath, typeof(Object));
  42. }
  43. #endif
  44. return this;
  45. }
  46. public string GetCreationLocation()
  47. {
  48. if (!string.IsNullOrEmpty(m_CreatedInFilePath))
  49. {
  50. var idx = m_CreatedInFilePath.LastIndexOf("\\") + 1;
  51. return string.Format("{0}, line {1} ({2})", m_CreatedInFilePath.Substring(idx), m_CreatedInFileLine, m_CreatedInFilePath);
  52. }
  53. return "";
  54. }
  55. public void Awake()
  56. {
  57. if (!Debug.isDebugBuild)
  58. Destroy(this);
  59. OnComponentCopy();
  60. }
  61. public void OnValidate()
  62. {
  63. if (Application.isEditor)
  64. OnComponentCopy();
  65. }
  66. private void OnComponentCopy()
  67. {
  68. if (m_ActionBase == null) return;
  69. var oldActionList = Resources.FindObjectsOfTypeAll(typeof(AssertionComponent)).Where(o => ((AssertionComponent)o).m_ActionBase == m_ActionBase && o != this);
  70. // if it's not a copy but a new component don't do anything
  71. if (!oldActionList.Any()) return;
  72. if (oldActionList.Count() > 1)
  73. Debug.LogWarning("More than one refence to comparer found. This shouldn't happen");
  74. var oldAction = oldActionList.First() as AssertionComponent;
  75. m_ActionBase = oldAction.m_ActionBase.CreateCopy(oldAction.gameObject, gameObject);
  76. }
  77. public void Start()
  78. {
  79. CheckAssertionFor(CheckMethod.Start);
  80. if (IsCheckMethodSelected(CheckMethod.AfterPeriodOfTime))
  81. {
  82. StartCoroutine("CheckPeriodically");
  83. }
  84. if (IsCheckMethodSelected(CheckMethod.Update))
  85. {
  86. m_CheckOnFrame = Time.frameCount + checkAfterFrames;
  87. }
  88. }
  89. public IEnumerator CheckPeriodically()
  90. {
  91. yield return new WaitForSeconds(checkAfterTime);
  92. CheckAssertionFor(CheckMethod.AfterPeriodOfTime);
  93. while (repeatCheckTime)
  94. {
  95. yield return new WaitForSeconds(repeatEveryTime);
  96. CheckAssertionFor(CheckMethod.AfterPeriodOfTime);
  97. }
  98. }
  99. public bool ShouldCheckOnFrame()
  100. {
  101. if (Time.frameCount > m_CheckOnFrame)
  102. {
  103. if (repeatCheckFrame)
  104. m_CheckOnFrame += repeatEveryFrame;
  105. else
  106. m_CheckOnFrame = Int32.MaxValue;
  107. return true;
  108. }
  109. return false;
  110. }
  111. public void OnDisable()
  112. {
  113. CheckAssertionFor(CheckMethod.OnDisable);
  114. }
  115. public void OnEnable()
  116. {
  117. CheckAssertionFor(CheckMethod.OnEnable);
  118. }
  119. public void OnDestroy()
  120. {
  121. CheckAssertionFor(CheckMethod.OnDestroy);
  122. }
  123. public void Update()
  124. {
  125. if (IsCheckMethodSelected(CheckMethod.Update) && ShouldCheckOnFrame())
  126. {
  127. CheckAssertionFor(CheckMethod.Update);
  128. }
  129. }
  130. public void FixedUpdate()
  131. {
  132. CheckAssertionFor(CheckMethod.FixedUpdate);
  133. }
  134. public void LateUpdate()
  135. {
  136. CheckAssertionFor(CheckMethod.LateUpdate);
  137. }
  138. public void OnControllerColliderHit()
  139. {
  140. CheckAssertionFor(CheckMethod.OnControllerColliderHit);
  141. }
  142. public void OnParticleCollision()
  143. {
  144. CheckAssertionFor(CheckMethod.OnParticleCollision);
  145. }
  146. public void OnJointBreak()
  147. {
  148. CheckAssertionFor(CheckMethod.OnJointBreak);
  149. }
  150. public void OnBecameInvisible()
  151. {
  152. CheckAssertionFor(CheckMethod.OnBecameInvisible);
  153. }
  154. public void OnBecameVisible()
  155. {
  156. CheckAssertionFor(CheckMethod.OnBecameVisible);
  157. }
  158. public void OnTriggerEnter()
  159. {
  160. CheckAssertionFor(CheckMethod.OnTriggerEnter);
  161. }
  162. public void OnTriggerExit()
  163. {
  164. CheckAssertionFor(CheckMethod.OnTriggerExit);
  165. }
  166. public void OnTriggerStay()
  167. {
  168. CheckAssertionFor(CheckMethod.OnTriggerStay);
  169. }
  170. public void OnCollisionEnter()
  171. {
  172. CheckAssertionFor(CheckMethod.OnCollisionEnter);
  173. }
  174. public void OnCollisionExit()
  175. {
  176. CheckAssertionFor(CheckMethod.OnCollisionExit);
  177. }
  178. public void OnCollisionStay()
  179. {
  180. CheckAssertionFor(CheckMethod.OnCollisionStay);
  181. }
  182. public void OnTriggerEnter2D()
  183. {
  184. CheckAssertionFor(CheckMethod.OnTriggerEnter2D);
  185. }
  186. public void OnTriggerExit2D()
  187. {
  188. CheckAssertionFor(CheckMethod.OnTriggerExit2D);
  189. }
  190. public void OnTriggerStay2D()
  191. {
  192. CheckAssertionFor(CheckMethod.OnTriggerStay2D);
  193. }
  194. public void OnCollisionEnter2D()
  195. {
  196. CheckAssertionFor(CheckMethod.OnCollisionEnter2D);
  197. }
  198. public void OnCollisionExit2D()
  199. {
  200. CheckAssertionFor(CheckMethod.OnCollisionExit2D);
  201. }
  202. public void OnCollisionStay2D()
  203. {
  204. CheckAssertionFor(CheckMethod.OnCollisionStay2D);
  205. }
  206. private void CheckAssertionFor(CheckMethod checkMethod)
  207. {
  208. if (IsCheckMethodSelected(checkMethod))
  209. {
  210. Assertions.CheckAssertions(this);
  211. }
  212. }
  213. public bool IsCheckMethodSelected(CheckMethod method)
  214. {
  215. return method == (checkMethods & method);
  216. }
  217. #region Assertion Component create methods
  218. public static T Create<T>(CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase
  219. {
  220. IAssertionComponentConfigurator configurator;
  221. return Create<T>(out configurator, checkOnMethods, gameObject, propertyPath);
  222. }
  223. public static T Create<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase
  224. {
  225. return CreateAssertionComponent<T>(out configurator, checkOnMethods, gameObject, propertyPath);
  226. }
  227. public static T Create<T>(CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, GameObject gameObject2, string propertyPath2) where T : ComparerBase
  228. {
  229. IAssertionComponentConfigurator configurator;
  230. return Create<T>(out configurator, checkOnMethods, gameObject, propertyPath, gameObject2, propertyPath2);
  231. }
  232. public static T Create<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, GameObject gameObject2, string propertyPath2) where T : ComparerBase
  233. {
  234. var comparer = CreateAssertionComponent<T>(out configurator, checkOnMethods, gameObject, propertyPath);
  235. comparer.compareToType = ComparerBase.CompareToType.CompareToObject;
  236. comparer.other = gameObject2;
  237. comparer.otherPropertyPath = propertyPath2;
  238. return comparer;
  239. }
  240. public static T Create<T>(CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, object constValue) where T : ComparerBase
  241. {
  242. IAssertionComponentConfigurator configurator;
  243. return Create<T>(out configurator, checkOnMethods, gameObject, propertyPath, constValue);
  244. }
  245. public static T Create<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, object constValue) where T : ComparerBase
  246. {
  247. var comparer = CreateAssertionComponent<T>(out configurator, checkOnMethods, gameObject, propertyPath);
  248. if (constValue == null)
  249. {
  250. comparer.compareToType = ComparerBase.CompareToType.CompareToNull;
  251. return comparer;
  252. }
  253. comparer.compareToType = ComparerBase.CompareToType.CompareToConstantValue;
  254. comparer.ConstValue = constValue;
  255. return comparer;
  256. }
  257. private static T CreateAssertionComponent<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase
  258. {
  259. var ac = gameObject.AddComponent<AssertionComponent>();
  260. ac.checkMethods = checkOnMethods;
  261. var comparer = ScriptableObject.CreateInstance<T>();
  262. ac.Action = comparer;
  263. ac.Action.go = gameObject;
  264. ac.Action.thisPropertyPath = propertyPath;
  265. configurator = ac;
  266. #if !UNITY_METRO
  267. var stackTrace = new StackTrace(true);
  268. var thisFileName = stackTrace.GetFrame(0).GetFileName();
  269. for (int i = 1; i < stackTrace.FrameCount; i++)
  270. {
  271. var stackFrame = stackTrace.GetFrame(i);
  272. if (stackFrame.GetFileName() != thisFileName)
  273. {
  274. string filePath = stackFrame.GetFileName().Substring(Application.dataPath.Length - "Assets".Length);
  275. ac.m_CreatedInFilePath = filePath;
  276. ac.m_CreatedInFileLine = stackFrame.GetFileLineNumber();
  277. break;
  278. }
  279. }
  280. #endif // if !UNITY_METRO
  281. return comparer;
  282. }
  283. #endregion
  284. #region AssertionComponentConfigurator
  285. public int UpdateCheckStartOnFrame { set { checkAfterFrames = value; } }
  286. public int UpdateCheckRepeatFrequency { set { repeatEveryFrame = value; } }
  287. public bool UpdateCheckRepeat { set { repeatCheckFrame = value; } }
  288. public float TimeCheckStartAfter { set { checkAfterTime = value; } }
  289. public float TimeCheckRepeatFrequency { set { repeatEveryTime = value; } }
  290. public bool TimeCheckRepeat { set { repeatCheckTime = value; } }
  291. public AssertionComponent Component { get { return this; } }
  292. #endregion
  293. }
  294. public interface IAssertionComponentConfigurator
  295. {
  296. /// <summary>
  297. /// If the assertion is evaluated in Update, after how many frame should the evaluation start. Deafult is 1 (first frame)
  298. /// </summary>
  299. int UpdateCheckStartOnFrame { set; }
  300. /// <summary>
  301. /// If the assertion is evaluated in Update and UpdateCheckRepeat is true, how many frame should pass between evaluations
  302. /// </summary>
  303. int UpdateCheckRepeatFrequency { set; }
  304. /// <summary>
  305. /// If the assertion is evaluated in Update, should the evaluation be repeated after UpdateCheckRepeatFrequency frames
  306. /// </summary>
  307. bool UpdateCheckRepeat { set; }
  308. /// <summary>
  309. /// If the assertion is evaluated after a period of time, after how many seconds the first evaluation should be done
  310. /// </summary>
  311. float TimeCheckStartAfter { set; }
  312. /// <summary>
  313. /// If the assertion is evaluated after a period of time and TimeCheckRepeat is true, after how many seconds should the next evaluation happen
  314. /// </summary>
  315. float TimeCheckRepeatFrequency { set; }
  316. /// <summary>
  317. /// If the assertion is evaluated after a period, should the evaluation happen again after TimeCheckRepeatFrequency seconds
  318. /// </summary>
  319. bool TimeCheckRepeat { set; }
  320. AssertionComponent Component { get; }
  321. }
  322. }