PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/BooCompiler.Tests/AbstractCompilerTestCase.cs

https://github.com/boo/boo-lang
C# | 320 lines | 246 code | 46 blank | 28 comment | 15 complexity | 33bd38b90a5d5893102456356adacfa4 MD5 | raw file
Possible License(s): GPL-2.0
  1. #region license
  2. // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. using System.Reflection;
  29. namespace BooCompiler.Tests
  30. {
  31. using System;
  32. using System.Diagnostics;
  33. using System.IO;
  34. using Boo.Lang.Compiler;
  35. using Boo.Lang.Compiler.IO;
  36. using Boo.Lang.Compiler.Steps;
  37. using Boo.Lang.Compiler.Pipelines;
  38. using NUnit.Framework;
  39. public abstract class AbstractCompilerTestCase
  40. {
  41. protected BooCompiler _compiler;
  42. protected CompilerParameters _parameters;
  43. protected string _baseTestCasesPath;
  44. protected StringWriter _output;
  45. protected bool VerifyGeneratedAssemblies
  46. {
  47. get
  48. {
  49. #if VISUAL_STUDIO
  50. return false;
  51. #else
  52. return GetEnvironmentFlag("peverify", true);
  53. #endif
  54. }
  55. }
  56. [TestFixtureSetUp]
  57. public virtual void SetUpFixture()
  58. {
  59. System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
  60. _baseTestCasesPath = Path.Combine(BooTestCaseUtil.TestCasesPath, GetRelativeTestCasesPath());
  61. _compiler = new BooCompiler();
  62. _parameters = _compiler.Parameters;
  63. _parameters.OutputWriter = _output = new StringWriter();
  64. _parameters.Pipeline = SetUpCompilerPipeline();
  65. _parameters.References.Add(typeof(NUnit.Framework.Assert).Assembly);
  66. _parameters.References.Add(typeof(AbstractCompilerTestCase).Assembly);
  67. _parameters.References.Add(typeof(BooCompiler).Assembly);
  68. _parameters.OutputAssembly = Path.Combine(Path.GetTempPath(), "testcase.exe");
  69. _parameters.Defines.Add("BOO_COMPILER_TESTS_DEFINED_CONDITIONAL", null);
  70. CustomizeCompilerParameters();
  71. if (VerifyGeneratedAssemblies) CopyDependencies();
  72. }
  73. protected virtual string GetRelativeTestCasesPath()
  74. {
  75. return "compilation";
  76. }
  77. protected virtual void CustomizeCompilerParameters()
  78. {
  79. }
  80. protected virtual void CopyDependencies()
  81. {
  82. CopyAssembly(typeof(Boo.Lang.List).Assembly);
  83. CopyAssembly(typeof(Boo.Lang.Extensions.MacroMacro).Assembly);
  84. CopyAssembly(GetType().Assembly);
  85. CopyAssembly(typeof(NUnit.Framework.Assert).Assembly);
  86. #if !VISUAL_STUDIO
  87. CopyAssembly(System.Reflection.Assembly.Load("BooModules"));
  88. #endif
  89. }
  90. protected void CopyAssembliesFromTestCasePath()
  91. {
  92. foreach (string fname in Directory.GetFiles(_baseTestCasesPath, "*.dll"))
  93. {
  94. CopyAssembly(fname);
  95. }
  96. }
  97. public void CopyAssembly(System.Reflection.Assembly assembly)
  98. {
  99. if (null == assembly) throw new ArgumentNullException("assembly");
  100. CopyAssembly(assembly.Location);
  101. }
  102. public void CopyAssembly(string location)
  103. {
  104. File.Copy(location, Path.Combine(Path.GetTempPath(), Path.GetFileName(location)), true);
  105. }
  106. [TestFixtureTearDown]
  107. public virtual void TearDownFixture()
  108. {
  109. Trace.Listeners.Clear();
  110. }
  111. [SetUp]
  112. public virtual void SetUpTest()
  113. {
  114. System.Threading.Thread current = System.Threading.Thread.CurrentThread;
  115. _parameters.Input.Clear();
  116. current.CurrentCulture = current.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
  117. }
  118. /// <summary>
  119. /// Override in derived classes to use a different pipeline.
  120. /// </summary>
  121. protected virtual CompilerPipeline SetUpCompilerPipeline()
  122. {
  123. CompilerPipeline pipeline = null;
  124. if (VerifyGeneratedAssemblies)
  125. {
  126. pipeline = new CompileToFileAndVerify();
  127. }
  128. else
  129. {
  130. pipeline = new CompileToMemory();
  131. }
  132. pipeline.Add(new RunAssembly());
  133. return pipeline;
  134. }
  135. bool GetEnvironmentFlag(string name, bool defaultValue)
  136. {
  137. string value = Environment.GetEnvironmentVariable(name);
  138. if (null == value)
  139. {
  140. return defaultValue;
  141. }
  142. return bool.Parse(value);
  143. }
  144. protected virtual void RunCompilerTestCase(string name)
  145. {
  146. string fname = GetTestCasePath(name);
  147. _parameters.Input.Add(new FileInput(fname));
  148. RunAndAssert();
  149. }
  150. protected void RunMultiFileTestCase(params string[] files)
  151. {
  152. foreach (string file in files)
  153. {
  154. _parameters.Input.Add(new FileInput(GetTestCasePath(file)));
  155. }
  156. RunAndAssert();
  157. }
  158. protected void RunAndAssert()
  159. {
  160. CompilerContext context;
  161. string output = Run(null, out context);
  162. string expected = context.CompileUnit.Modules[0].Documentation;
  163. if (null == expected)
  164. {
  165. expected = "";
  166. }
  167. Assert.AreEqual(expected.Trim(), output.Trim(), _parameters.Input[0].Name);
  168. }
  169. protected string RunString(string code)
  170. {
  171. return RunString(code, null);
  172. }
  173. protected string RunString(string code, string stdin)
  174. {
  175. _parameters.Input.Add(new StringInput("<teststring>", code));
  176. CompilerContext context;
  177. return Run(stdin, out context);
  178. }
  179. private bool HasErrors(CompilerContext context)
  180. {
  181. return context.Errors.Count > 0;
  182. }
  183. protected string Run(string stdin, out CompilerContext context)
  184. {
  185. TextWriter oldStdOut = Console.Out;
  186. TextReader oldStdIn = Console.In;
  187. try
  188. {
  189. Console.SetOut(_output);
  190. if (null != stdin)
  191. {
  192. Console.SetIn(new StringReader(stdin));
  193. }
  194. context = _compiler.Run();
  195. if (HasErrors(context) && !IgnoreErrors)
  196. {
  197. Assert.Fail(GetFirstInputName(context)
  198. + ": "
  199. + context.Errors.ToString(false)
  200. + context.Warnings.ToString());
  201. }
  202. return _output.ToString().Replace("\r\n", "\n");
  203. }
  204. finally
  205. {
  206. _output.GetStringBuilder().Length = 0;
  207. Console.SetOut(oldStdOut);
  208. Console.SetIn(oldStdIn);
  209. }
  210. }
  211. protected virtual bool IgnoreErrors
  212. {
  213. get
  214. {
  215. return false;
  216. }
  217. }
  218. string GetFirstInputName(CompilerContext context)
  219. {
  220. return context.Parameters.Input[0].Name;
  221. }
  222. public string BaseTestCasesPath
  223. {
  224. get { return _baseTestCasesPath; }
  225. }
  226. protected virtual string GetTestCasePath(string fname)
  227. {
  228. return Path.Combine(_baseTestCasesPath, fname);
  229. }
  230. class AssemblyResolver
  231. {
  232. string _path;
  233. public AssemblyResolver(string path)
  234. {
  235. _path = path;
  236. }
  237. public System.Reflection.Assembly AssemblyResolve(object sender, ResolveEventArgs args)
  238. {
  239. string simpleName = GetSimpleName(args.Name);
  240. string basePath = Path.Combine(_path, simpleName);
  241. Assembly asm = ProbeFile(basePath + ".dll");
  242. if (asm != null) return asm;
  243. return ProbeFile(basePath + ".exe");
  244. }
  245. private string GetSimpleName(string name)
  246. {
  247. return System.Text.RegularExpressions.Regex.Split(name, ",\\s*")[0];
  248. }
  249. private Assembly ProbeFile(string fname)
  250. {
  251. if (!File.Exists(fname)) return null;
  252. try
  253. {
  254. return Assembly.LoadFrom(fname);
  255. }
  256. catch (Exception x)
  257. {
  258. Console.Error.WriteLine(x);
  259. }
  260. return null;
  261. }
  262. }
  263. protected System.ResolveEventHandler InstallAssemblyResolver(string path)
  264. {
  265. ResolveEventHandler handler = new ResolveEventHandler(new AssemblyResolver(path).AssemblyResolve);
  266. AppDomain.CurrentDomain.AssemblyResolve += handler;
  267. return handler;
  268. }
  269. protected void RemoveAssemblyResolver(System.ResolveEventHandler handler)
  270. {
  271. AppDomain.CurrentDomain.AssemblyResolve -= handler;
  272. }
  273. }
  274. }