UnitTests.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.CompilerServices;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using BansheeEngine;
  8. using DebugUnit = System.Diagnostics.Debug;
  9. namespace BansheeEditor
  10. {
  11. /// <summary>
  12. /// Contains various managed unit tests.
  13. /// </summary>
  14. class UnitTests
  15. {
  16. /// <summary>
  17. /// Triggers an exception when a unit test condition fails.
  18. /// </summary>
  19. /// <param name="success">True if the unit test condition succeeded, false otherwise.</param>
  20. static void Assert(bool success)
  21. {
  22. if (!success)
  23. throw new InvalidOperationException("Unit test failed.");
  24. }
  25. /// <summary>
  26. /// Tests managed object serialization and deserialization.
  27. /// </summary>
  28. static void UnitTest1_ManagedSerialization()
  29. {
  30. SceneObject otherSO = new SceneObject("OtherSO");
  31. UT1_Component2 dbgComponent2 = otherSO.AddComponent<UT1_Component2>();
  32. dbgComponent2.a2 = 33;
  33. SceneObject so = new SceneObject("TestSO");
  34. UT1_Component1 dbgComponent = so.AddComponent<UT1_Component1>();
  35. dbgComponent.a = 5;
  36. dbgComponent.b = "SomeTestVal";
  37. dbgComponent.complex.someValue = 19;
  38. dbgComponent.complex.anotherValue = "AnotherValue";
  39. dbgComponent.complex2.someValue2 = 21;
  40. dbgComponent.complex2.anotherValue2 = "AnotherValue2";
  41. dbgComponent.arrA = new int[5];
  42. dbgComponent.arrA[4] = 5;
  43. dbgComponent.arrB = new string[5];
  44. dbgComponent.arrB[4] = "ArrAnotherValue";
  45. dbgComponent.arrComplex = new UT1_SerzObj[5];
  46. dbgComponent.arrComplex[4].someValue = 99;
  47. dbgComponent.arrComplex[4].anotherValue = "ArrComplexAnotherValue";
  48. dbgComponent.arrComplex2 = new UT1_SerzCls[5];
  49. dbgComponent.arrComplex2[4] = new UT1_SerzCls();
  50. dbgComponent.arrComplex2[4].someValue2 = 101;
  51. dbgComponent.arrComplex2[4].anotherValue2 = "ArrComplex2AnotherValue";
  52. dbgComponent.listA = new List<int>();
  53. dbgComponent.listA.Add(5);
  54. dbgComponent.listB = new List<string>();
  55. dbgComponent.listB.Add("ListAnotherValue");
  56. dbgComponent.listB.Add(null);
  57. dbgComponent.listComplex = new List<UT1_SerzObj>();
  58. dbgComponent.listComplex.Add(new UT1_SerzObj());
  59. dbgComponent.listComplex.Add(new UT1_SerzObj(99, "ListComplexAnotherValue"));
  60. dbgComponent.listComplex2 = new List<UT1_SerzCls>();
  61. dbgComponent.listComplex2.Add(new UT1_SerzCls());
  62. dbgComponent.listComplex2[0].someValue2 = 101;
  63. dbgComponent.listComplex2[0].anotherValue2 = "ListComplexAnotherValue";
  64. dbgComponent.listComplex2.Add(null);
  65. dbgComponent.dictA = new Dictionary<int, string>();
  66. dbgComponent.dictA[5] = "value";
  67. dbgComponent.dictA[10] = "anotherValue";
  68. dbgComponent.dictB = new Dictionary<string, UT1_SerzObj>();
  69. dbgComponent.dictB["key1"] = new UT1_SerzObj(99, "DictComplexValue");
  70. dbgComponent.otherComponent = dbgComponent2;
  71. dbgComponent.otherSO = otherSO;
  72. Internal_UT1_GameObjectClone(so);
  73. System.Diagnostics.Debug.Assert(so.GetNumChildren() == 1);
  74. for (int i = 0; i < so.GetNumChildren(); i++)
  75. {
  76. SceneObject childSO = so.GetChild(i);
  77. UT1_Component1 otherComponent = childSO.GetComponent<UT1_Component1>();
  78. DebugUnit.Assert(otherComponent.a == 5);
  79. DebugUnit.Assert(otherComponent.b == "SomeTestVal");
  80. DebugUnit.Assert(otherComponent.complex.someValue == 19);
  81. DebugUnit.Assert(otherComponent.complex2.anotherValue2 == "AnotherValue2");
  82. DebugUnit.Assert(otherComponent.arrA[4] == 5);
  83. DebugUnit.Assert(otherComponent.arrB[4] == "ArrAnotherValue");
  84. DebugUnit.Assert(otherComponent.arrComplex[4].someValue == 99);
  85. DebugUnit.Assert(otherComponent.arrComplex2[4].anotherValue2 == "ArrComplex2AnotherValue");
  86. DebugUnit.Assert(otherComponent.listA[0] == 5);
  87. DebugUnit.Assert(otherComponent.listB[0] == "ListAnotherValue");
  88. DebugUnit.Assert(otherComponent.listComplex[1].someValue == 99);
  89. DebugUnit.Assert(otherComponent.listComplex2[0].anotherValue2 == "ListComplexAnotherValue");
  90. }
  91. so.Destroy();
  92. otherSO.Destroy();
  93. }
  94. /// <summary>
  95. /// Tests serializable properties used for inspection.
  96. /// </summary>
  97. static void UnitTest2_SerializableProperties()
  98. {
  99. SerializableObject obj = new SerializableObject(typeof(UT1_SerzCls), new UT1_SerzCls());
  100. SerializableProperty prop = obj.Fields[0].GetProperty();
  101. prop.SetValue(33);
  102. DebugUnit.Assert(prop.GetValue<int>() == 33);
  103. SerializableProperty prop2 = obj.Fields[2].GetProperty();
  104. UT1_SerzCls child = new UT1_SerzCls();
  105. child.anotherValue2 = "potato";
  106. prop2.SetValue<UT1_SerzCls>(child);
  107. DebugUnit.Assert(prop2.GetValue<UT1_SerzCls>() != null);
  108. DebugUnit.Assert(prop2.GetValue<UT1_SerzCls>().anotherValue2 == "potato");
  109. }
  110. /// <summary>
  111. /// Tests managed diff creation used by prefabs.
  112. /// </summary>
  113. static void UnitTest3_ManagedDiff()
  114. {
  115. UT_DiffObj original = new UT_DiffObj();
  116. UT_DiffObj modified = new UT_DiffObj();
  117. modified.plain2 = "banana";
  118. modified.complex = new UT_DiffChildObj();
  119. modified.complex2 = null;
  120. modified.complex3.plain2 = "tomato";
  121. modified.arrPlain1 = new[] {-1, -2, -3, -4};
  122. modified.arrPlain2[2] = "cherry";
  123. modified.arrComplex = new UT_DiffChildObj[3];
  124. modified.arrComplex2[0].plain1 = -10;
  125. modified.listPlain1[0] = -20;
  126. modified.listPlain2 = new List<string>();
  127. modified.listComplex = new List<UT_DiffChildObj>();
  128. modified.listComplex.Add(new UT_DiffChildObj());
  129. modified.listComplex2[1].plain2 = "orange";
  130. modified.dictPlain1.Remove(20);
  131. modified.dictPlain1[-30] = -30;
  132. modified.dictComplex = new Dictionary<int, UT_DiffChildObj>();
  133. modified.dictComplex[-40] = new UT_DiffChildObj();
  134. modified.dictComplex2[31].plain1 = -50;
  135. Internal_UT3_GenerateDiff(original, modified);
  136. Internal_UT3_ApplyDiff(original);
  137. DebugUnit.Assert(original.plain1 == modified.plain1);
  138. DebugUnit.Assert(original.plain2 == modified.plain2);
  139. DebugUnit.Assert(original.complex.plain2 == modified.complex.plain2);
  140. DebugUnit.Assert(original.complex2 == modified.complex2);
  141. DebugUnit.Assert(original.complex3.plain2 == modified.complex3.plain2);
  142. DebugUnit.Assert(original.arrPlain1.Length == modified.arrPlain1.Length);
  143. for (int i = 0; i < original.arrPlain1.Length; i++)
  144. DebugUnit.Assert(original.arrPlain1[i] == modified.arrPlain1[i]);
  145. for (int i = 0; i < original.arrPlain2.Length; i++)
  146. DebugUnit.Assert(original.arrPlain2[i] == modified.arrPlain2[i]);
  147. for (int i = 0; i < original.arrComplex.Length; i++)
  148. DebugUnit.Assert(original.arrComplex[i] == modified.arrComplex[i]);
  149. DebugUnit.Assert(original.arrComplex2[0].plain1 == modified.arrComplex2[0].plain1);
  150. for (int i = 0; i < original.listPlain1.Count; i++)
  151. DebugUnit.Assert(original.listPlain1[i] == modified.listPlain1[i]);
  152. DebugUnit.Assert(original.listPlain2.Count == modified.listPlain2.Count);
  153. for (int i = 0; i < original.listComplex.Count; i++)
  154. DebugUnit.Assert(original.listComplex[i].plain1 == modified.listComplex[i].plain1);
  155. DebugUnit.Assert(original.listComplex2[1].plain2 == modified.listComplex2[1].plain2);
  156. foreach (var entry in modified.dictPlain1)
  157. {
  158. if (!original.dictPlain1.ContainsKey(entry.Key))
  159. DebugUnit.Assert(false);
  160. DebugUnit.Assert(entry.Value == original.dictPlain1[entry.Key]);
  161. }
  162. foreach (var entry in modified.dictPlain2)
  163. {
  164. if (!original.dictPlain2.ContainsKey(entry.Key))
  165. DebugUnit.Assert(false);
  166. DebugUnit.Assert(entry.Value == original.dictPlain2[entry.Key]);
  167. }
  168. foreach (var entry in modified.dictComplex)
  169. {
  170. if (!original.dictComplex.ContainsKey(entry.Key))
  171. DebugUnit.Assert(false);
  172. DebugUnit.Assert(entry.Value.plain1 == original.dictComplex[entry.Key].plain1);
  173. }
  174. foreach (var entry in modified.dictComplex2)
  175. {
  176. if (!original.dictComplex2.ContainsKey(entry.Key))
  177. DebugUnit.Assert(false);
  178. DebugUnit.Assert(entry.Value.plain1 == original.dictComplex2[entry.Key].plain1);
  179. }
  180. }
  181. /// <summary>
  182. /// Tests saving, loading and updating of prefabs.
  183. /// </summary>
  184. private static void UnitTest4_Prefabs()
  185. {
  186. if (!EditorApplication.IsProjectLoaded)
  187. {
  188. Debug.LogWarning("Skipping unit test as no project is loaded.");
  189. return;
  190. }
  191. if (EditorApplication.IsSceneModified())
  192. {
  193. Debug.LogWarning("Cannot perform unit test as the current scene is modified.");
  194. return;
  195. }
  196. Action PrintSceneState = () =>
  197. {
  198. SceneObject root = Scene.Root;
  199. Stack<SceneObject> todo = new Stack<SceneObject>();
  200. todo.Push(root);
  201. StringBuilder output = new StringBuilder();
  202. while (todo.Count > 0)
  203. {
  204. SceneObject so = todo.Pop();
  205. int numChildren = so.GetNumChildren();
  206. for (int i = numChildren - 1; i >= 0; i--)
  207. {
  208. SceneObject child = so.GetChild(i);
  209. output.AppendLine(child.Name);
  210. todo.Push(child);
  211. }
  212. }
  213. Debug.Log(output);
  214. };
  215. string oldScene = Scene.ActiveSceneUUID;
  216. Scene.Clear();
  217. try
  218. {
  219. // Simple scene save & load
  220. {
  221. {
  222. // unitTest4Scene_0.prefab:
  223. // so0 (Comp1)
  224. // - so0_0
  225. // - so0_1 (Comp1)
  226. // - so0_1_0 (Comp1)
  227. // so1 (Comp2)
  228. // - so1_0
  229. SceneObject so0 = new SceneObject("so0");
  230. SceneObject so1 = new SceneObject("so1");
  231. SceneObject so0_0 = new SceneObject("so0_0");
  232. SceneObject so0_1 = new SceneObject("so0_1");
  233. SceneObject so1_0 = new SceneObject("so1_0");
  234. SceneObject so0_1_0 = new SceneObject("so0_1_0");
  235. so0_0.Parent = so0;
  236. so0_1.Parent = so0;
  237. so1_0.Parent = so1;
  238. so0_1_0.Parent = so0_1;
  239. so0_1_0.Position = new Vector3(10.0f, 15.0f, 20.0f);
  240. so0_1.Position = new Vector3(1.0f, 2.0f, 3.0f);
  241. so1_0.Position = new Vector3(0, 123.0f, 0.0f);
  242. UT1_Component1 comp0 = so0.AddComponent<UT1_Component1>();
  243. UT1_Component2 comp1 = so1.AddComponent<UT1_Component2>();
  244. UT1_Component1 comp1_1 = so0_1.AddComponent<UT1_Component1>();
  245. UT1_Component1 comp0_1_0 = so0_1_0.AddComponent<UT1_Component1>();
  246. comp0.otherSO = so0_1_0;
  247. comp0.otherComponent = comp1;
  248. comp1_1.b = "originalValue2";
  249. comp0_1_0.b = "testValue";
  250. comp0_1_0.otherSO = so0;
  251. comp0_1_0.otherComponent2 = comp0;
  252. EditorApplication.SaveScene("unitTest4Scene_0.prefab");
  253. }
  254. {
  255. EditorApplication.LoadScene("unitTest4Scene_0.prefab");
  256. SceneObject sceneRoot = Scene.Root;
  257. SceneObject so0 = sceneRoot.FindChild("so0", false);
  258. SceneObject so1 = sceneRoot.FindChild("so1", false);
  259. SceneObject so0_0 = so0.FindChild("so0_0", false);
  260. SceneObject so0_1 = so0.FindChild("so0_1", false);
  261. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  262. Assert(so0_0 != null);
  263. Assert(so0_1 != null);
  264. Assert(so0_1_0 != null);
  265. UT1_Component1 comp0 = so0.GetComponent<UT1_Component1>();
  266. UT1_Component2 comp1 = so1.GetComponent<UT1_Component2>();
  267. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  268. Assert(comp0 != null);
  269. Assert(comp1 != null);
  270. Assert(comp0_1_0 != null);
  271. Assert(comp0_1_0.b == "testValue");
  272. Assert(comp0.otherSO == so0_1_0);
  273. Assert(comp0.otherComponent == comp1);
  274. Assert(comp0_1_0.otherSO == so0);
  275. Assert(comp0_1_0.otherComponent2 == comp0);
  276. }
  277. }
  278. // Load & save a scene that contains a prefab and references its objects
  279. {
  280. {
  281. // unitTest4Scene_1.prefab:
  282. // parentSO0
  283. // - [unitTest4Scene_0.prefab]
  284. // parentSO1
  285. // - parentSO1_0 (Comp1)
  286. Scene.Clear();
  287. SceneObject parentSO0 = new SceneObject("parentSO0", false);
  288. SceneObject parentSO1 = new SceneObject("parentSO1", false);
  289. SceneObject parentSO1_0 = new SceneObject("parentSO1_0", false);
  290. parentSO1_0.Parent = parentSO1;
  291. UT1_Component1 parentComp1_0 = parentSO1_0.AddComponent<UT1_Component1>();
  292. Prefab scene0Prefab = ProjectLibrary.Load<Prefab>("unitTest4Scene_0.prefab");
  293. SceneObject prefabInstance = scene0Prefab.Instantiate();
  294. prefabInstance.Parent = parentSO0;
  295. SceneObject so0 = prefabInstance.FindChild("so0", false);
  296. SceneObject so1 = prefabInstance.FindChild("so1", false);
  297. SceneObject so0_1 = so0.FindChild("so0_1", false);
  298. SceneObject so1_0 = so1.FindChild("so1_0", false);
  299. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  300. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  301. parentComp1_0.otherSO = so1_0;
  302. parentComp1_0.otherComponent2 = comp0_1_0;
  303. EditorApplication.SaveScene("unitTest4Scene_1.prefab");
  304. }
  305. {
  306. EditorApplication.LoadScene("unitTest4Scene_1.prefab");
  307. SceneObject parentSO0 = Scene.Root.FindChild("parentSO0", false);
  308. SceneObject parentSO1 = Scene.Root.FindChild("parentSO1", false);
  309. SceneObject parentSO1_0 = parentSO1.FindChild("parentSO1_0", false);
  310. UT1_Component1 parentComp1_0 = parentSO1_0.GetComponent<UT1_Component1>();
  311. SceneObject prefabInstance = parentSO0.GetChild(0);
  312. SceneObject so0 = prefabInstance.FindChild("so0", false);
  313. SceneObject so1 = prefabInstance.FindChild("so1", false);
  314. SceneObject so0_1 = so0.FindChild("so0_1", false);
  315. SceneObject so1_0 = so1.FindChild("so1_0", false);
  316. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  317. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  318. Assert(parentComp1_0.otherSO == so1_0);
  319. Assert(parentComp1_0.otherComponent2 == comp0_1_0);
  320. }
  321. }
  322. // Modify prefab, reload the scene and ensure it is updated with modified prefab
  323. {
  324. {
  325. // unitTest4Scene_0.prefab:
  326. // so0
  327. // - so0_1 (Comp1)
  328. // - so0_1_0 (Comp1)
  329. // so1 (Comp1, Comp2)
  330. // - so1_0
  331. // - so1_1
  332. Scene.Load("unitTest4Scene_0.prefab");
  333. SceneObject sceneRoot = Scene.Root;
  334. SceneObject so0 = sceneRoot.FindChild("so0", false);
  335. SceneObject so0_0 = so0.FindChild("so0_0", false);
  336. SceneObject so0_1 = so0.FindChild("so0_1", false);
  337. SceneObject so1 = sceneRoot.FindChild("so1", false);
  338. SceneObject so1_0 = so1.FindChild("so1_0", false);
  339. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  340. SceneObject so1_1 = new SceneObject("so1_1");
  341. so1_1.Parent = so1;
  342. so0.RemoveComponent<UT1_Component1>();
  343. UT1_Component1 comp1 = so1.AddComponent<UT1_Component1>();
  344. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  345. so0_0.Destroy();
  346. comp1.otherSO = so1_0;
  347. comp1.otherComponent2 = comp0_1_0;
  348. comp0_1_0.otherSO = so1_1;
  349. comp0_1_0.otherComponent2 = comp1;
  350. comp0_1_0.a = 123;
  351. comp0_1_0.b = "modifiedValue";
  352. so1.Name = "so1_modified";
  353. so1.Position = new Vector3(0, 999.0f, 0.0f);
  354. EditorApplication.SaveScene("unitTest4Scene_0.prefab");
  355. }
  356. {
  357. EditorApplication.LoadScene("unitTest4Scene_1.prefab");
  358. SceneObject parentSO0 = Scene.Root.FindChild("parentSO0", false);
  359. SceneObject parentSO1 = Scene.Root.FindChild("parentSO1", false);
  360. SceneObject parentSO1_0 = parentSO1.FindChild("parentSO1_0", false);
  361. UT1_Component1 parentComp1_0 = parentSO1_0.GetComponent<UT1_Component1>();
  362. SceneObject prefabInstance = parentSO0.GetChild(0);
  363. SceneObject so0 = prefabInstance.FindChild("so0", false);
  364. SceneObject so1 = prefabInstance.FindChild("so1_modified", false);
  365. SceneObject so0_0 = so0.FindChild("so0_0", false);
  366. SceneObject so0_1 = so0.FindChild("so0_1", false);
  367. SceneObject so1_0 = so1.FindChild("so1_0", false);
  368. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  369. SceneObject so1_1 = so1.FindChild("so1_1", false);
  370. UT1_Component1 comp0 = so0.GetComponent<UT1_Component1>();
  371. UT1_Component1 comp1 = so1.GetComponent<UT1_Component1>();
  372. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  373. Assert(parentComp1_0.otherSO == so1_0);
  374. Assert(parentComp1_0.otherComponent2 == comp0_1_0);
  375. Assert(so1_1 != null);
  376. Assert(so0_0 == null);
  377. Assert(comp0 == null);
  378. Assert(comp0_1_0.otherSO == so1_1);
  379. Assert(comp0_1_0.otherComponent2 == comp1);
  380. Assert(comp0_1_0.a == 123);
  381. Assert(comp0_1_0.b == "modifiedValue");
  382. Assert(comp1.otherSO == so1_0);
  383. Assert(comp1.otherComponent2 == comp0_1_0);
  384. Assert(MathEx.ApproxEquals(so1.Position.y, 999.0f));
  385. }
  386. }
  387. // Make instance specific changes to the prefab, modify the prefab itself and ensure
  388. // both changes persist
  389. {
  390. // Create new scene referencing the prefab and make instance modifications
  391. {
  392. // unitTest4Scene_2.prefab:
  393. // parent2SO0
  394. // - [unitTest4Scene_0.prefab]
  395. // parent2SO1
  396. // - parent2SO1_0 (Comp1)
  397. // unitTest4Scene_0.prefab (unitTest4Scene_2.prefab instance):
  398. // so0 (Comp1(INSTANCE))
  399. // - so0_0 (INSTANCE)
  400. // - so0_1 (Comp1)
  401. // - so0_1_0 (Comp1)
  402. // so1 (Comp2)
  403. // - so1_0
  404. Scene.Clear();
  405. SceneObject parent2SO0 = new SceneObject("parent2SO0");
  406. SceneObject parent2SO1 = new SceneObject("parent2SO1");
  407. SceneObject parent2SO1_0 = new SceneObject("parent2SO1_0");
  408. parent2SO1_0.Parent = parent2SO1;
  409. UT1_Component1 parentComp1_0 = parent2SO1_0.AddComponent<UT1_Component1>();
  410. Prefab scene0Prefab = ProjectLibrary.Load<Prefab>("unitTest4Scene_0.prefab");
  411. SceneObject prefabInstance = scene0Prefab.Instantiate();
  412. prefabInstance.Parent = parent2SO0;
  413. SceneObject so0 = prefabInstance.FindChild("so0", false);
  414. SceneObject so1 = prefabInstance.FindChild("so1", false);
  415. SceneObject so0_1 = so1.FindChild("so0_1", false);
  416. SceneObject so1_0 = so1.FindChild("so1_0", false);
  417. SceneObject so1_1 = so1.FindChild("so1_1", false);
  418. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  419. UT1_Component2 comp1 = so1.GetComponent<UT1_Component2>();
  420. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  421. UT1_Component1 comp0_1 = so0_1.GetComponent<UT1_Component1>();
  422. SceneObject so0_0 = new SceneObject("so0_0");
  423. so0_0.Parent = so0;
  424. UT1_Component1 comp0 = so0.AddComponent<UT1_Component1>();
  425. so1.RemoveComponent<UT1_Component1>();
  426. so1_1.Destroy();
  427. comp0.otherSO = so0_1_0;
  428. comp0.otherComponent = comp1;
  429. parentComp1_0.otherSO = so1_0;
  430. parentComp1_0.otherComponent2 = comp0_1_0;
  431. comp0_1_0.otherSO = parent2SO1_0;
  432. comp0_1_0.otherComponent2 = parentComp1_0;
  433. comp0_1_0.b = "instanceValue";
  434. comp0_1.b = "instanceValue2";
  435. EditorApplication.SaveScene("unitTest4Scene_2.prefab");
  436. }
  437. // Reload the scene and ensure instance modifications remain
  438. {
  439. EditorApplication.LoadScene("unitTest4Scene_2.prefab");
  440. SceneObject root = Scene.Root;
  441. SceneObject parent2SO0 = root.FindChild("parent2SO0", false);
  442. SceneObject parent2SO1 = root.FindChild("parent2SO1", false);
  443. SceneObject parent2SO1_0 = parent2SO1.FindChild("parent2SO1_0", false);
  444. SceneObject prefabInstance = parent2SO0.GetChild(0);
  445. SceneObject so0 = prefabInstance.FindChild("so0", false);
  446. SceneObject so1 = prefabInstance.FindChild("so1", false);
  447. SceneObject so0_0 = so0.FindChild("so0_0", false);
  448. SceneObject so0_1 = so0.FindChild("so0_1", false);
  449. SceneObject so1_0 = so1.FindChild("so1_0", false);
  450. SceneObject so1_1 = so1.FindChild("so1_1", false);
  451. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  452. UT1_Component1 parentComp1_0 = parent2SO1_0.GetComponent<UT1_Component1>();
  453. UT1_Component1 comp0 = so0.GetComponent<UT1_Component1>();
  454. UT1_Component2 comp1 = so1.GetComponent<UT1_Component2>();
  455. UT1_Component1 comp11 = so1.GetComponent<UT1_Component1>();
  456. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  457. UT1_Component1 comp0_1 = so0_1.GetComponent<UT1_Component1>();
  458. Assert(so0_0 != null);
  459. Assert(comp0 != null);
  460. Assert(so1_1 == null);
  461. Assert(comp11 == null);
  462. Assert(comp0.otherSO == so0_1_0);
  463. Assert(comp0.otherComponent == comp1);
  464. Assert(parentComp1_0.otherSO == so1_0);
  465. Assert(parentComp1_0.otherComponent2 == comp0_1_0);
  466. Assert(comp0_1_0.otherSO == parent2SO1_0);
  467. Assert(comp0_1_0.otherComponent2 == parentComp1_0);
  468. Assert(comp0_1_0.b == "instanceValue");
  469. Assert(comp0_1.b == "instanceValue2");
  470. }
  471. // Load original scene and ensure instance modifications didn't influence it
  472. {
  473. EditorApplication.LoadScene("unitTest4Scene_1.prefab");
  474. SceneObject parentSO0 = Scene.Root.FindChild("parentSO0", false);
  475. SceneObject parentSO1 = Scene.Root.FindChild("parentSO1", false);
  476. SceneObject parentSO1_0 = parentSO1.FindChild("parentSO1_0", false);
  477. UT1_Component1 parentComp1_0 = parentSO1_0.GetComponent<UT1_Component1>();
  478. SceneObject prefabInstance = parentSO0.GetChild(0);
  479. SceneObject so0 = prefabInstance.FindChild("so0", false);
  480. SceneObject so1 = prefabInstance.FindChild("so1_modified", false);
  481. SceneObject so0_0 = so0.FindChild("so0_0", false);
  482. SceneObject so0_1 = so0.FindChild("so0_1", false);
  483. SceneObject so1_0 = so1.FindChild("so1_0", false);
  484. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  485. SceneObject so1_1 = so1.FindChild("so1_1", false);
  486. UT1_Component1 comp0 = so0.GetComponent<UT1_Component1>();
  487. UT1_Component1 comp1 = so1.GetComponent<UT1_Component1>();
  488. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  489. UT1_Component1 comp0_1 = so0_1.GetComponent<UT1_Component1>();
  490. Assert(parentComp1_0.otherSO == so1_0);
  491. Assert(parentComp1_0.otherComponent2 == comp0_1_0);
  492. Assert(so1_1 != null);
  493. Assert(so0_0 == null);
  494. Assert(comp0 == null);
  495. Assert(comp0_1_0.otherSO == so1_1);
  496. Assert(comp0_1_0.otherComponent2 == comp1);
  497. Assert(comp0_1_0.a == 123);
  498. Assert(comp0_1_0.b == "modifiedValue");
  499. Assert(comp1.otherSO == so1_0);
  500. Assert(comp1.otherComponent2 == comp0_1_0);
  501. Assert(comp0_1.b == "originalValue2");
  502. Assert(MathEx.ApproxEquals(so1.Position.y, 999.0f));
  503. }
  504. // Modify prefab and ensure both prefab and instance modifications remain
  505. {
  506. // unitTest4Scene_0.prefab:
  507. // so0 (Comp1)
  508. // - so0_1
  509. // - so0_1_0 (Comp1)
  510. // so1 (Comp1, Comp2)
  511. // - so1_1
  512. // - so1_2 (Comp1)
  513. // unitTest4Scene_0.prefab (unitTest4Scene_2.prefab instance):
  514. // so0 (Comp1)
  515. // - so0_0
  516. // - so0_1 (Comp1)
  517. // - so0_1_0 (Comp1)
  518. // so1 (Comp2)
  519. // - so1_2 (Comp1)
  520. Scene.Load("unitTest4Scene_0.prefab");
  521. SceneObject sceneRoot = Scene.Root;
  522. SceneObject so0 = sceneRoot.FindChild("so0", false);
  523. SceneObject so0_1 = so0.FindChild("so0_1", false);
  524. SceneObject so1 = sceneRoot.FindChild("so1_modified", false);
  525. SceneObject so1_0 = so1.FindChild("so1_0", false);
  526. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  527. SceneObject so1_2 = new SceneObject("so1_2");
  528. so1_2.Parent = so1;
  529. so0.AddComponent<UT1_Component1>();
  530. so0_1.RemoveComponent<UT1_Component1>();
  531. so1_0.Destroy();
  532. UT1_Component1 comp3 = so1_2.AddComponent<UT1_Component1>();
  533. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  534. comp0_1_0.b = "modifiedValueAgain";
  535. so1.Name = "so1_modifiedAgain";
  536. comp3.otherSO = so0_1;
  537. comp3.otherComponent2 = comp0_1_0;
  538. EditorApplication.SaveScene("unitTest4Scene_0.prefab");
  539. }
  540. // Reload the scene and ensure both instance and prefab modifications remain
  541. {
  542. EditorApplication.LoadScene("unitTest4Scene_2.prefab");
  543. SceneObject root = Scene.Root;
  544. SceneObject parent2SO0 = root.FindChild("parent2SO0", false);
  545. SceneObject parent2SO1 = root.FindChild("parent2SO1", false);
  546. SceneObject parent2SO1_0 = parent2SO1.FindChild("parent2SO1_0", false);
  547. SceneObject prefabInstance = parent2SO0.GetChild(0);
  548. SceneObject so0 = prefabInstance.FindChild("so0", false);
  549. SceneObject so1 = prefabInstance.FindChild("so1", false);
  550. SceneObject so0_0 = so0.FindChild("so0_0", false);
  551. SceneObject so0_1 = so0.FindChild("so0_1", false);
  552. SceneObject so1_0 = so1.FindChild("so1_0", false);
  553. SceneObject so1_1 = so1.FindChild("so1_1", false);
  554. SceneObject so1_2 = so1.FindChild("so1_2", false);
  555. SceneObject so0_1_0 = so0_1.FindChild("so0_1_0", false);
  556. UT1_Component1 parentComp1_0 = parent2SO1_0.GetComponent<UT1_Component1>();
  557. UT1_Component1 comp0 = so0.GetComponent<UT1_Component1>();
  558. UT1_Component2 comp1 = so1.GetComponent<UT1_Component2>();
  559. UT1_Component1 comp11 = so1.GetComponent<UT1_Component1>();
  560. UT1_Component1 comp0_1 = so1_1.GetComponent<UT1_Component1>();
  561. UT1_Component1 comp0_1_0 = so0_1_0.GetComponent<UT1_Component1>();
  562. UT1_Component1 comp3 = so1_2.AddComponent<UT1_Component1>();
  563. // Check instance modifications (they should override any prefab modifications)
  564. Assert(so0_0 != null);
  565. Assert(comp0 != null);
  566. Assert(so1_1 == null);
  567. Assert(comp11 == null);
  568. Assert(comp0.otherSO == so0_1_0);
  569. Assert(comp0.otherComponent == comp1);
  570. Assert(parentComp1_0.otherSO == so1_0);
  571. Assert(parentComp1_0.otherComponent2 == comp0_1_0);
  572. Assert(comp0_1_0.otherSO == parent2SO1_0);
  573. Assert(comp0_1_0.otherComponent2 == parentComp1_0);
  574. Assert(comp0_1_0.b == "instanceValue");
  575. // Check prefab modifications
  576. Assert(comp0_1 != null);
  577. Assert(so1_0 == null);
  578. Assert(so1.Name == "so1_modifiedAgain");
  579. Assert(comp3.otherSO == so0_1);
  580. Assert(comp3.otherComponent2 == comp0_1_0);
  581. }
  582. }
  583. }
  584. finally
  585. {
  586. PrintSceneState();
  587. if (!string.IsNullOrEmpty(oldScene))
  588. Scene.Load(ProjectLibrary.GetPath(oldScene));
  589. else
  590. Scene.Clear();
  591. ProjectLibrary.Delete("unitTest4Scene_0.prefab");
  592. ProjectLibrary.Delete("unitTest4Scene_1.prefab");
  593. ProjectLibrary.Delete("unitTest4Scene_2.prefab");
  594. }
  595. }
  596. /// <summary>
  597. /// Runs all tests.
  598. /// </summary>
  599. static void RunTests()
  600. {
  601. UnitTest1_ManagedSerialization();
  602. UnitTest2_SerializableProperties();
  603. UnitTest3_ManagedDiff();
  604. UnitTest4_Prefabs();
  605. }
  606. [MethodImpl(MethodImplOptions.InternalCall)]
  607. private static extern void Internal_UT1_GameObjectClone(SceneObject so);
  608. [MethodImpl(MethodImplOptions.InternalCall)]
  609. private static extern void Internal_UT3_GenerateDiff(UT_DiffObj oldObj, UT_DiffObj newObj);
  610. [MethodImpl(MethodImplOptions.InternalCall)]
  611. private static extern void Internal_UT3_ApplyDiff(UT_DiffObj obj);
  612. }
  613. }