A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using System.Text;
5using UnityEngine;
6using UnityEngine.TestRunner.NUnitExtensions.Runner;
7using UnityEngine.TestTools.Logging;
8using UnityEngine.TestTools.NUnitExtensions;
9
10namespace UnityEditor.TestTools.TestRunner
11{
12 [Serializable]
13 internal class TestRunnerStateSerializer : IStateSerializer
14 {
15 private const BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
16
17 [SerializeField]
18 private HideFlags m_OriginalHideFlags;
19
20 [SerializeField]
21 private bool m_ShouldRestore;
22
23 [SerializeField]
24 private string m_TestObjectTypeName;
25
26 [SerializeField]
27 private ScriptableObject m_TestObject;
28
29 [SerializeField]
30 private string m_TestObjectTxt;
31
32 [SerializeField]
33 private long StartTicks;
34
35 [SerializeField]
36 private double StartTimeOA;
37
38 [SerializeField]
39 private string output;
40
41 [SerializeField]
42 private LogMatch[] m_ExpectedLogs;
43
44 public bool ShouldRestore()
45 {
46 return m_ShouldRestore;
47 }
48
49 public void SaveContext()
50 {
51 var currentContext = UnityTestExecutionContext.CurrentContext;
52
53 if (currentContext.TestObject != null)
54 {
55 m_TestObjectTypeName = currentContext.TestObject.GetType().AssemblyQualifiedName;
56 m_TestObject = null;
57 m_TestObjectTxt = null;
58 if (currentContext.TestObject is ScriptableObject)
59 {
60 m_TestObject = currentContext.TestObject as ScriptableObject;
61 m_OriginalHideFlags = m_TestObject.hideFlags;
62 m_TestObject.hideFlags |= HideFlags.DontSave;
63 }
64 else
65 {
66 m_TestObjectTxt = JsonUtility.ToJson(currentContext.TestObject);
67 }
68 }
69
70 output = currentContext.CurrentResult.Output;
71 StartTicks = currentContext.StartTicks;
72 StartTimeOA = currentContext.StartTime.ToOADate();
73 if (LogScope.HasCurrentLogScope())
74 {
75 m_ExpectedLogs = LogScope.Current.ExpectedLogs.ToArray();
76 }
77
78 m_ShouldRestore = true;
79 }
80
81 public void RestoreContext()
82 {
83 var currentContext = UnityTestExecutionContext.CurrentContext;
84
85 var outputProp = currentContext.CurrentResult.GetType().BaseType.GetField("_output", Flags);
86 (outputProp.GetValue(currentContext.CurrentResult) as StringBuilder).Append(output);
87
88 currentContext.StartTicks = StartTicks;
89 currentContext.StartTime = DateTime.FromOADate(StartTimeOA);
90 if (LogScope.HasCurrentLogScope())
91 {
92 LogScope.Current.ExpectedLogs = new Queue<LogMatch>(m_ExpectedLogs);
93 }
94
95 m_ShouldRestore = false;
96 }
97
98 public bool CanRestoreFromScriptableObject(Type requestedType)
99 {
100 if (m_TestObject == null)
101 {
102 return false;
103 }
104 return m_TestObjectTypeName == requestedType.AssemblyQualifiedName;
105 }
106
107 public ScriptableObject RestoreScriptableObjectInstance()
108 {
109 if (m_TestObject == null)
110 {
111 Debug.LogError("No object to restore");
112 return null;
113 }
114 EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
115 var temp = m_TestObject;
116 m_TestObject = null;
117 m_TestObjectTypeName = null;
118 return temp;
119 }
120
121 public bool CanRestoreFromJson(Type requestedType)
122 {
123 if (string.IsNullOrEmpty(m_TestObjectTxt))
124 {
125 return false;
126 }
127 return m_TestObjectTypeName == requestedType.AssemblyQualifiedName;
128 }
129
130 public void RestoreClassFromJson(ref object instance)
131 {
132 if (string.IsNullOrEmpty(m_TestObjectTxt))
133 {
134 Debug.LogWarning("No JSON representation to restore");
135 return;
136 }
137 JsonUtility.FromJsonOverwrite(m_TestObjectTxt, instance);
138 m_TestObjectTxt = null;
139 m_TestObjectTypeName = null;
140 }
141
142 private void OnPlayModeStateChanged(PlayModeStateChange state)
143 {
144 if (m_TestObject == null)
145 {
146 EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
147 return;
148 }
149
150 //We set the DontSave flag here because the ScriptableObject would be nulled right before entering EditMode
151 if (state == PlayModeStateChange.ExitingPlayMode)
152 {
153 m_TestObject.hideFlags |= HideFlags.DontSave;
154 }
155 else if (state == PlayModeStateChange.EnteredEditMode)
156 {
157 m_TestObject.hideFlags = m_OriginalHideFlags;
158 EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
159 }
160 }
161 }
162}