SchemaConverterTests.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. using System;
  2. using AssetBank.Editor.SchemaConverter.Data.Output;
  3. using AssetBank.Editor.Tools;
  4. using AssetBank.Settings;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using Newtonsoft.Json;
  8. using Newtonsoft.Json.Linq;
  9. using NUnit.Framework;
  10. using UnityEditor;
  11. using UnityEngine;
  12. using Debug = UnityEngine.Debug;
  13. namespace AssetBank.Editor.SchemaConverter.Tests
  14. {
  15. [TestFixture]
  16. public class SchemaConverterTests
  17. {
  18. private const string SampleScenePath = "Assets/Scenes/SampleScene.unity";
  19. private string _tempDirectory;
  20. private string _rawJsonPath;
  21. private string _trimmedJsonPath;
  22. private string _hierarchyJsonPath;
  23. private string _hierarchyAndPrefabsJsonPath;
  24. private string _fullGraphJsonPath;
  25. [SetUp]
  26. public void SetUp()
  27. {
  28. _tempDirectory = Path.Combine("Library", "SchemaConverterTestTemp");
  29. Directory.CreateDirectory(_tempDirectory);
  30. _rawJsonPath = Path.Combine(_tempDirectory, "raw_scene.json");
  31. _trimmedJsonPath = Path.Combine(_tempDirectory, "trimmed_scene.json");
  32. _hierarchyJsonPath = Path.Combine(_tempDirectory, "hierarchy_only.json");
  33. _hierarchyAndPrefabsJsonPath = Path.Combine(_tempDirectory, "hierarchy_and_prefabs.json");
  34. _fullGraphJsonPath = Path.Combine(_tempDirectory, "full_graph.json");
  35. }
  36. [TearDown]
  37. public void TearDown()
  38. {
  39. if (Directory.Exists(_tempDirectory))
  40. {
  41. Directory.Delete(_tempDirectory, true);
  42. }
  43. }
  44. [Test, Order(1)]
  45. public void CanConvertSceneToRawJson()
  46. {
  47. var pythonExe = FindPythonExecutable();
  48. var conversionScript = GetConversionScriptPath();
  49. Assert.IsNotNull(pythonExe, "Python executable not found.");
  50. Assert.IsNotNull(conversionScript, "Conversion script 'convert_scene.py' not found.");
  51. var success = ExecutePythonConversion(SampleScenePath, _rawJsonPath, pythonExe, conversionScript);
  52. Assert.IsTrue(success, "Python conversion script failed to execute.");
  53. Assert.IsTrue(File.Exists(_rawJsonPath), "Raw JSON file was not created.");
  54. Assert.Greater(new FileInfo(_rawJsonPath).Length, 0, "Raw JSON file is empty.");
  55. Debug.Log($"Successfully created raw JSON at: {_rawJsonPath}");
  56. }
  57. [Test, Order(2)]
  58. public void CanTrimRawJson()
  59. {
  60. // Ensure the first step has run and created the file.
  61. if (!File.Exists(_rawJsonPath))
  62. {
  63. CanConvertSceneToRawJson();
  64. }
  65. Assert.IsTrue(File.Exists(_rawJsonPath), "Prerequisite step 'CanConvertSceneToRawJson' failed to produce an output file.");
  66. var rawJson = File.ReadAllText(_rawJsonPath);
  67. var settings = ProjectExporterSettings.GetOrCreateSettings();
  68. var trimmedJson = JsonDataTrimmer.Process(rawJson, settings);
  69. File.WriteAllText(_trimmedJsonPath, trimmedJson);
  70. Assert.IsTrue(File.Exists(_trimmedJsonPath), "Trimmed JSON file was not created.");
  71. Assert.Greater(new FileInfo(_trimmedJsonPath).Length, 0, "Trimmed JSON file is empty.");
  72. Debug.Log($"Successfully created trimmed JSON at: {_trimmedJsonPath}");
  73. }
  74. [Test, Order(3)]
  75. public void CanProcessHierarchyOnly()
  76. {
  77. // Ensure the prerequisite step has run.
  78. if (!File.Exists(_trimmedJsonPath))
  79. {
  80. CanTrimRawJson();
  81. }
  82. Assert.IsTrue(File.Exists(_trimmedJsonPath), "Prerequisite step 'CanTrimRawJson' failed to produce an output file.");
  83. var trimmedJson = File.ReadAllText(_trimmedJsonPath);
  84. // Run the conversion but only use the hierarchy part of the result.
  85. var sceneGraph = JsonSchemaConverter.ConvertToSceneGraph(trimmedJson);
  86. var hierarchyJson = JsonConvert.SerializeObject(sceneGraph.hierarchy, Formatting.Indented);
  87. File.WriteAllText(_hierarchyJsonPath, hierarchyJson);
  88. Assert.IsTrue(File.Exists(_hierarchyJsonPath), "Hierarchy-only JSON file was not created.");
  89. Assert.Greater(new FileInfo(_hierarchyJsonPath).Length, 2, "Hierarchy-only JSON file is empty (should be at least '[]').");
  90. Debug.Log($"Successfully created hierarchy-only JSON at: {_hierarchyJsonPath}");
  91. }
  92. [Test, Order(4)]
  93. public void CanProcessHierarchyAndPrefabs()
  94. {
  95. // Ensure the prerequisite step has run.
  96. if (!File.Exists(_trimmedJsonPath))
  97. {
  98. CanTrimRawJson();
  99. }
  100. Assert.IsTrue(File.Exists(_trimmedJsonPath), "Prerequisite step 'CanTrimRawJson' failed to produce an output file.");
  101. var trimmedJson = File.ReadAllText(_trimmedJsonPath);
  102. // Run the conversion and serialize the hierarchy and prefabs sections.
  103. var sceneGraph = JsonSchemaConverter.ConvertToSceneGraph(trimmedJson);
  104. var result = new JObject
  105. {
  106. ["hierarchy"] = JToken.FromObject(sceneGraph.hierarchy),
  107. ["prefabs"] = JToken.FromObject(sceneGraph.prefabs)
  108. };
  109. var outputJson = result.ToString(Formatting.Indented);
  110. File.WriteAllText(_hierarchyAndPrefabsJsonPath, outputJson);
  111. Assert.IsTrue(File.Exists(_hierarchyAndPrefabsJsonPath), "Hierarchy and prefabs JSON file was not created.");
  112. Assert.Greater(new FileInfo(_hierarchyAndPrefabsJsonPath).Length, 2, "Hierarchy and prefabs JSON file is empty.");
  113. Debug.Log($"Successfully created hierarchy and prefabs JSON at: {_hierarchyAndPrefabsJsonPath}");
  114. }
  115. [Test, Order(5)]
  116. public void CanProcessFullGraphSuccessfully()
  117. {
  118. // Ensure the prerequisite step has run.
  119. if (!File.Exists(_trimmedJsonPath))
  120. {
  121. CanTrimRawJson();
  122. }
  123. Assert.IsTrue(File.Exists(_trimmedJsonPath), "Prerequisite step 'CanTrimRawJson' failed to produce an output file.");
  124. var trimmedJson = File.ReadAllText(_trimmedJsonPath);
  125. // This test now asserts that the conversion completes WITHOUT throwing an exception.
  126. string finalJson = null;
  127. Assert.DoesNotThrow(() =>
  128. {
  129. finalJson = JsonSchemaConverter.Convert(trimmedJson);
  130. }, "The conversion process threw an unexpected exception.");
  131. File.WriteAllText(_fullGraphJsonPath, finalJson);
  132. Assert.IsTrue(File.Exists(_fullGraphJsonPath), "Full graph JSON file was not created.");
  133. Assert.Greater(new FileInfo(_fullGraphJsonPath).Length, 2, "Full graph JSON file is empty.");
  134. // A good final check is to ensure no warnings were generated.
  135. var sceneGraph = JsonConvert.DeserializeObject<SceneGraph>(finalJson);
  136. Assert.IsNull(sceneGraph.metadata.warnings, "The conversion generated unexpected warnings.");
  137. Debug.Log($"Successfully created full graph JSON at: {_fullGraphJsonPath}");
  138. }
  139. #region Helper Methods
  140. private string FindPythonExecutable()
  141. {
  142. var projectRoot = Path.GetDirectoryName(Application.dataPath);
  143. var venvPath = Path.Combine(projectRoot, "venv", "bin", "python3");
  144. if (File.Exists(venvPath)) return venvPath;
  145. venvPath = Path.Combine(projectRoot, "venv", "bin", "python");
  146. if (File.Exists(venvPath)) return venvPath;
  147. // Fallback for system python
  148. return "python3";
  149. }
  150. private string GetConversionScriptPath()
  151. {
  152. var guids = AssetDatabase.FindAssets("convert_scene");
  153. if (guids.Length == 0) return null;
  154. var projectRoot = Path.GetDirectoryName(Application.dataPath);
  155. return Path.Combine(projectRoot, AssetDatabase.GUIDToAssetPath(guids[0]));
  156. }
  157. private bool ExecutePythonConversion(string assetPath, string jsonOutputPath, string pythonExe, string scriptPath)
  158. {
  159. var projectRoot = Path.GetDirectoryName(Application.dataPath);
  160. var absoluteAssetPath = Path.Combine(projectRoot, assetPath);
  161. var arguments = $"\"{scriptPath}\" \"{absoluteAssetPath}\" \"{jsonOutputPath}\"";
  162. var process = new Process
  163. {
  164. StartInfo = new ProcessStartInfo
  165. {
  166. FileName = pythonExe,
  167. Arguments = arguments,
  168. RedirectStandardOutput = true,
  169. RedirectStandardError = true,
  170. UseShellExecute = false,
  171. CreateNoWindow = true
  172. }
  173. };
  174. process.Start();
  175. string error = process.StandardError.ReadToEnd();
  176. process.WaitForExit();
  177. if (process.ExitCode == 0) return true;
  178. Debug.LogError($"Failed to convert {assetPath}. Error: {error}");
  179. return false;
  180. }
  181. #endregion
  182. }
  183. }