Program.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using System.Web;
  9. using Newtonsoft.Json;
  10. using Path = Fluent.IO.Path;
  11. namespace Jint.Tests.Scaffolding
  12. {
  13. class Program
  14. {
  15. private static string[] suites = new string[]
  16. {
  17. "http://test262.ecmascript.org/json/ch06.json",
  18. "http://test262.ecmascript.org/json/ch07.json",
  19. "http://test262.ecmascript.org/json/ch08.json",
  20. "http://test262.ecmascript.org/json/ch09.json",
  21. "http://test262.ecmascript.org/json/ch10.json",
  22. "http://test262.ecmascript.org/json/ch11.json",
  23. "http://test262.ecmascript.org/json/ch12.json",
  24. "http://test262.ecmascript.org/json/ch13.json",
  25. "http://test262.ecmascript.org/json/ch14.json",
  26. "http://test262.ecmascript.org/json/ch15.json",
  27. };
  28. private const string SpecsUrl = "http://www.ecma-international.org/ecma-262/5.1/";
  29. private static string _specs;
  30. private static Path _testPath ;
  31. private static Path _suitePath;
  32. private static string _classTemplate;
  33. private static string _methodTemplate;
  34. private static Dictionary<string, List<TestEntry>> categorizedTests = new Dictionary<string, List<TestEntry>>();
  35. static void Main(string[] args)
  36. {
  37. var assemblyPath = typeof(Program).Assembly.Location;
  38. var assemblyDirectory = Path.Get(assemblyPath);
  39. _testPath = assemblyDirectory.Parent().Parent().Parent().Parent().Combine("Jint.Tests.Ecma");
  40. _suitePath = _testPath;
  41. if (!_suitePath.Exists)
  42. {
  43. _suitePath.CreateDirectory();
  44. }
  45. _classTemplate = File.ReadAllText("ClassTemplate.txt");
  46. _methodTemplate = File.ReadAllText("MethodTemplate.txt");
  47. foreach(var url in suites) {
  48. var content = new WebClient().DownloadString(url);
  49. dynamic suite = JsonConvert.DeserializeObject(content);
  50. var collection = suite.testsCollection;
  51. var tests = collection.tests;
  52. Console.Write(".");
  53. foreach (var test in tests)
  54. {
  55. byte[] data = Convert.FromBase64String((string)test.code);
  56. string decodedString = Encoding.UTF8.GetString(data);
  57. RenderTest(
  58. decodedString,
  59. (string)test.commentary,
  60. (string)test.description,
  61. (string)test.path,
  62. test.negative != null
  63. );
  64. }
  65. }
  66. foreach (var category in categorizedTests.Keys)
  67. {
  68. var file = _testPath.Combine("Ecma").Combine(category + ".cs");
  69. var methods = new StringBuilder();
  70. foreach (var test in categorizedTests[category])
  71. {
  72. methods.Append(test.Test);
  73. methods.AppendLine();
  74. }
  75. var fileContent = _classTemplate;
  76. fileContent = fileContent.Replace("$$Methods$$", methods.ToString());
  77. fileContent = fileContent.Replace("$$ClassName$$", GetClassName(category));
  78. File.WriteAllText(file.FullPath, fileContent);
  79. }
  80. }
  81. private static void RenderTest(string code, string commentary, string description, string path, bool negative)
  82. {
  83. var file = _suitePath.Combine(path.Substring(0, path.Length - 3) + ".cs");
  84. if (!file.Parent().Exists)
  85. {
  86. file.Parent().CreateDirectory();
  87. }
  88. var className = GetClassName(file.FileNameWithoutExtension);
  89. var category = GetCategory(file.FileNameWithoutExtension);
  90. var content = _methodTemplate;
  91. var methodName = GetMethodName(String.IsNullOrEmpty(commentary) ? description : commentary);
  92. var uniqueMethodName = methodName;
  93. if (!categorizedTests.ContainsKey(category))
  94. {
  95. categorizedTests.Add(category, new List<TestEntry>());
  96. }
  97. if (categorizedTests[category].Any(x => x.MethodName == methodName))
  98. {
  99. uniqueMethodName += categorizedTests[category].Count(x => x.MethodName == methodName) + 1;
  100. }
  101. content = content.Replace("$$ClassName$$", className);
  102. content = content.Replace("$$Source$$", EncodeCSharpString(path));
  103. content = content.Replace("$$Description$$", EncodeCSharpString(description));
  104. content = content.Replace("$$Category$$", category);
  105. content = content.Replace("$$MethodName$$", uniqueMethodName);
  106. content = content.Replace("$$Negative$$", negative ? "true" : "false");
  107. content = NormalizeLineEndings(content);
  108. categorizedTests[category].Add(new TestEntry
  109. {
  110. MethodName = methodName,
  111. Test = content
  112. });
  113. File.WriteAllText(_suitePath.Combine(path).FullPath, code);
  114. }
  115. private static readonly Regex R = new Regex(@"(\r\n)|(\n)", RegexOptions.Multiline);
  116. private static string NormalizeLineEndings(string text)
  117. {
  118. return R.Replace(text, Environment.NewLine);
  119. }
  120. private static string EncodeCSharpString(string value)
  121. {
  122. if (String.IsNullOrEmpty(value))
  123. {
  124. return String.Empty;
  125. }
  126. return value.Replace("\"", "\"\"");
  127. }
  128. private static string GetCategory(string filename)
  129. {
  130. string category = filename;
  131. category = filename.Split('-', '_').First();
  132. if (category.StartsWith("S"))
  133. {
  134. category = category.Substring(1);
  135. }
  136. return category;
  137. }
  138. public static string GetClassName(string filename)
  139. {
  140. return "Test_" + filename.Replace(".", "_").Replace("-", "__");
  141. }
  142. public static string GetMethodName(string description)
  143. {
  144. var simplified = Sanitize(description);
  145. var result = new StringBuilder(simplified.Length);
  146. var previousIsSpace = true;
  147. for (int i = 0; i < simplified.Length; i++)
  148. {
  149. if (simplified[i] == '-')
  150. {
  151. previousIsSpace = true;
  152. continue;
  153. }
  154. if (previousIsSpace)
  155. {
  156. result.Append(simplified[i].ToString().ToUpper());
  157. }
  158. else
  159. {
  160. result.Append(simplified[i].ToString().ToLower());
  161. }
  162. previousIsSpace = Char.IsDigit(simplified[i]);
  163. }
  164. return result.ToString();
  165. }
  166. public static string Sanitize(string text)
  167. {
  168. if (String.IsNullOrWhiteSpace(text))
  169. return "";
  170. var result = new char[text.Length];
  171. var cursor = 0;
  172. var previousIsNotLetter = false;
  173. for (var i = 0; i < text.Length; i++)
  174. {
  175. char current = text[i];
  176. if (IsLetter(current) || (Char.IsDigit(current) && cursor > 0))
  177. {
  178. if (previousIsNotLetter && i != 0 && cursor > 0)
  179. {
  180. result[cursor++] = '-';
  181. }
  182. result[cursor++] = Char.ToLowerInvariant(current);
  183. previousIsNotLetter = false;
  184. }
  185. else
  186. {
  187. previousIsNotLetter = true;
  188. }
  189. }
  190. return new string(result, 0, cursor);
  191. }
  192. public static bool IsLetter(char c)
  193. {
  194. return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
  195. }
  196. private class TestEntry
  197. {
  198. public string Test;
  199. public string MethodName;
  200. }
  201. }
  202. }