Utils.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Numerics;
  5. using System.Text;
  6. using NUnit.Framework;
  7. namespace SharpGLTF
  8. {
  9. static class NUnitUtils
  10. {
  11. public static string ToShortDisplayPath(this string path)
  12. {
  13. var dir = System.IO.Path.GetDirectoryName(path);
  14. var fxt = System.IO.Path.GetFileName(path);
  15. const int maxdir = 12;
  16. if (dir.Length > maxdir)
  17. {
  18. dir = "..." + dir.Substring(dir.Length - maxdir);
  19. }
  20. return System.IO.Path.Combine(dir, fxt);
  21. }
  22. public static string GetAttachmentPath(this TestContext context, string fileName, bool ensureDirectoryExists = false)
  23. {
  24. var path = System.IO.Path.Combine(context.TestDirectory, "TestResults", $"{context.Test.ID}");
  25. var dir = path;
  26. if (!string.IsNullOrWhiteSpace(fileName))
  27. {
  28. if (System.IO.Path.IsPathRooted(fileName)) throw new ArgumentException(nameof(fileName), "path must be a relative path");
  29. path = System.IO.Path.Combine(path, fileName);
  30. dir = System.IO.Path.GetDirectoryName(path);
  31. }
  32. System.IO.Directory.CreateDirectory(dir);
  33. return path;
  34. }
  35. public static void AttachToCurrentTest(this Schema2.ModelRoot model, string fileName)
  36. {
  37. // find the output path for the current test
  38. fileName = TestContext.CurrentContext.GetAttachmentPath(fileName, true);
  39. if (fileName.ToLower().EndsWith(".glb"))
  40. {
  41. model.SaveGLB(fileName);
  42. }
  43. else if (fileName.ToLower().EndsWith(".gltf"))
  44. {
  45. model.SaveGLTF(fileName, Newtonsoft.Json.Formatting.Indented);
  46. }
  47. else if (fileName.ToLower().EndsWith(".obj"))
  48. {
  49. fileName = fileName.Replace(" ", "_");
  50. Schema2.Schema2Toolkit.SaveAsWavefront(model, fileName);
  51. }
  52. // Attach the saved file to the current test
  53. TestContext.AddTestAttachment(fileName);
  54. }
  55. public static void AttachToCurrentTest(this Schema2.ModelRoot model, string fileName, Schema2.Animation animation, float time)
  56. {
  57. fileName = fileName.Replace(" ", "_");
  58. // find the output path for the current test
  59. fileName = TestContext.CurrentContext.GetAttachmentPath(fileName, true);
  60. Schema2.Schema2Toolkit.SaveAsWavefront(model, fileName, animation, time);
  61. // Attach the saved file to the current test
  62. TestContext.AddTestAttachment(fileName);
  63. }
  64. public static void AttachToCurrentTest<TvG, TvM, TvS>(this Geometry.MeshBuilder<TvG, TvM, TvS> mesh, string fileName)
  65. where TvG : struct, Geometry.VertexTypes.IVertexGeometry
  66. where TvM : struct, Geometry.VertexTypes.IVertexMaterial
  67. where TvS : struct, Geometry.VertexTypes.IVertexSkinning
  68. {
  69. var gl2model = Schema2.ModelRoot.CreateModel();
  70. var gl2mesh = Schema2.Schema2Toolkit.CreateMeshes(gl2model, mesh).First();
  71. var node = gl2model.UseScene(0).CreateNode();
  72. node.Mesh = gl2mesh;
  73. gl2model.AttachToCurrentTest(fileName);
  74. }
  75. public static void AttachText(this TestContext context, string fileName, string[] lines)
  76. {
  77. fileName = context.GetAttachmentPath(fileName, true);
  78. System.IO.File.WriteAllLines(fileName, lines.ToArray());
  79. TestContext.AddTestAttachment(fileName);
  80. }
  81. public static void AttachShowDirLink(this TestContext context)
  82. {
  83. context.AttachLink("📂 Show Directory", context.GetAttachmentPath(string.Empty));
  84. }
  85. public static void AttachGltfValidatorLinks(this TestContext context)
  86. {
  87. context.AttachLink("🌍 Khronos Validator", "http://github.khronos.org/glTF-Validator/");
  88. context.AttachLink("🌍 BabylonJS Sandbox", "https://sandbox.babylonjs.com/");
  89. context.AttachLink("🌍 Don McCurdy Sandbox", "https://gltf-viewer.donmccurdy.com/");
  90. context.AttachLink("🌍 VirtualGIS Cesium Sandbox", "https://www.virtualgis.io/gltfviewer/");
  91. }
  92. public static void AttachLink(this TestContext context, string linkPath, string targetPath)
  93. {
  94. linkPath = context.GetAttachmentPath(linkPath);
  95. linkPath = ShortcutUtils.CreateLink(linkPath, targetPath);
  96. TestContext.AddTestAttachment(linkPath);
  97. }
  98. }
  99. static class DownloadUtils
  100. {
  101. private static readonly Object _DownloadMutex = new object();
  102. public static void SyncronizeGitRepository(string remoteUrl, string localDirectoryPath)
  103. {
  104. if (!System.IO.Path.IsPathRooted(localDirectoryPath)) throw new ArgumentException(nameof(localDirectoryPath));
  105. lock (_DownloadMutex)
  106. {
  107. if (LibGit2Sharp.Repository.Discover(localDirectoryPath) == null)
  108. {
  109. TestContext.Progress.WriteLine($"Cloning {remoteUrl} can take several minutes; Please wait...");
  110. LibGit2Sharp.Repository.Clone(remoteUrl, localDirectoryPath);
  111. TestContext.Progress.WriteLine($"... Clone Completed");
  112. return;
  113. }
  114. using (var repo = new LibGit2Sharp.Repository(localDirectoryPath))
  115. {
  116. var options = new LibGit2Sharp.PullOptions
  117. {
  118. FetchOptions = new LibGit2Sharp.FetchOptions()
  119. };
  120. var r = LibGit2Sharp.Commands.Pull(repo, new LibGit2Sharp.Signature("Anonymous", "[email protected]", new DateTimeOffset(DateTime.Now)), options);
  121. TestContext.Progress.WriteLine($"{remoteUrl} is {r.Status}");
  122. }
  123. }
  124. }
  125. public static string DownloadFile(string remoteUri, string localFilePath)
  126. {
  127. if (!System.IO.Path.IsPathRooted(localFilePath)) throw new ArgumentException(nameof(localFilePath));
  128. lock (_DownloadMutex)
  129. {
  130. if (System.IO.File.Exists(localFilePath)) return localFilePath; // we check again because we could have downloaded the file while waiting.
  131. TestContext.Progress.WriteLine($"Downloading {remoteUri}... Please Wait...");
  132. var dir = System.IO.Path.GetDirectoryName(localFilePath);
  133. System.IO.Directory.CreateDirectory(dir);
  134. using (var wc = new System.Net.WebClient())
  135. {
  136. wc.DownloadFile(remoteUri, localFilePath);
  137. }
  138. if (localFilePath.ToLower().EndsWith(".zip"))
  139. {
  140. TestContext.Progress.WriteLine($"Extracting {localFilePath}...");
  141. var extractPath = System.IO.Path.Combine(dir, System.IO.Path.GetFileNameWithoutExtension(localFilePath));
  142. System.IO.Compression.ZipFile.ExtractToDirectory(localFilePath, extractPath);
  143. }
  144. return localFilePath;
  145. }
  146. }
  147. }
  148. static class ShortcutUtils
  149. {
  150. public static string CreateLink(string localLinkPath, string targetPath)
  151. {
  152. if (string.IsNullOrWhiteSpace(localLinkPath)) throw new ArgumentNullException(nameof(localLinkPath));
  153. if (string.IsNullOrWhiteSpace(targetPath)) throw new ArgumentNullException(nameof(targetPath));
  154. if (!Uri.TryCreate(targetPath, UriKind.Absolute, out Uri uri)) throw new UriFormatException(nameof(targetPath));
  155. var sb = new StringBuilder();
  156. sb.AppendLine("[{000214A0-0000-0000-C000-000000000046}]");
  157. sb.AppendLine("Prop3=19,11");
  158. sb.AppendLine("[InternetShortcut]");
  159. sb.AppendLine("IDList=");
  160. sb.AppendLine($"URL={uri.AbsoluteUri}");
  161. if (uri.IsFile)
  162. {
  163. sb.AppendLine("IconIndex=1");
  164. string icon = targetPath.Replace('\\', '/');
  165. sb.AppendLine("IconFile=" + icon);
  166. }
  167. else
  168. {
  169. sb.AppendLine("IconIndex=0");
  170. }
  171. localLinkPath = System.IO.Path.ChangeExtension(localLinkPath, ".url");
  172. System.IO.File.WriteAllText(localLinkPath, sb.ToString());
  173. return localLinkPath;
  174. }
  175. }
  176. static class VectorUtils
  177. {
  178. public static Single NextSingle(this Random rnd)
  179. {
  180. return (Single)rnd.NextDouble();
  181. }
  182. public static Vector2 NextVector2(this Random rnd)
  183. {
  184. return new Vector2(rnd.NextSingle(), rnd.NextSingle());
  185. }
  186. public static Vector3 NextVector3(this Random rnd)
  187. {
  188. return new Vector3(rnd.NextSingle(), rnd.NextSingle(), rnd.NextSingle());
  189. }
  190. public static Vector4 NextVector4(this Random rnd)
  191. {
  192. return new Vector4(rnd.NextSingle(), rnd.NextSingle(), rnd.NextSingle(), rnd.NextSingle());
  193. }
  194. public static void AreEqual(Vector4 a, Vector4 b, double delta = 0)
  195. {
  196. Assert.AreEqual(a.X, b.X, delta);
  197. Assert.AreEqual(a.Y, b.Y, delta);
  198. Assert.AreEqual(a.Z, b.Z, delta);
  199. Assert.AreEqual(a.W, b.W, delta);
  200. }
  201. }
  202. }