22fbfbc2b86acd8a4e0994dc7f04077246af6c2f
[mono.git] / mcs / class / System / Test / Microsoft.VisualBasic / VBCodeProviderTest.cs
1 //\r
2 // Microsoft.VisualBasic.VBCodeProvider.cs\r
3 //\r
4 // Author:\r
5 //   Jochen Wezel (jwezel@compumaster.de)\r
6 //\r
7 // (C) 2003 Jochen Wezel (CompuMaster GmbH)\r
8 //\r
9 // Last modifications:\r
10 // 2003-12-10 JW: publishing of this file\r
11 //\r
12 \r
13 using System;\r
14 using System.CodeDom;\r
15 using System.CodeDom.Compiler;\r
16 using System.ComponentModel;\r
17 using System.Collections.Specialized;\r
18 using System.Globalization;\r
19 using System.Reflection;\r
20 using System.Diagnostics;\r
21 using System.IO;\r
22 using Microsoft.VisualBasic;\r
23 using NUnit.Framework;\r
24 \r
25 namespace MonoTests.Microsoft.VisualBasic\r
26 {\r
27         enum OsType\r
28         {\r
29                 Windows,\r
30                 Unix,\r
31                 Mac\r
32         }\r
33 \r
34         [TestFixture]\r
35         public class VBCodeProviderTest\r
36         {\r
37                 private string _tempDir;\r
38                 private CodeDomProvider _codeProvider;\r
39                 private static OsType OS;\r
40                 private static char DSC = Path.DirectorySeparatorChar;\r
41 \r
42                 private static readonly string _sourceTest1 = "Public Class Test1" +\r
43                         Environment.NewLine + "End Class";\r
44                 private static readonly string _sourceTest2 = "Public Class Test2" +\r
45                         Environment.NewLine + "End Class";\r
46 \r
47                 [SetUp]\r
48                 public void GetReady ()\r
49                 {\r
50                         if ('/' == DSC) {\r
51                                 OS = OsType.Unix;\r
52                         } else if ('\\' == DSC) {\r
53                                 OS = OsType.Windows;\r
54                         } else {\r
55                                 OS = OsType.Mac;\r
56                         }\r
57 \r
58                         _codeProvider = new VBCodeProvider ();\r
59                         _tempDir = CreateTempDirectory ();\r
60                 }\r
61 \r
62                 [TearDown]\r
63                 public void TearDown ()\r
64                 {\r
65                         RemoveDirectory (_tempDir);\r
66                 }\r
67 \r
68                 [Test]\r
69                 public void FileExtension ()\r
70                 {\r
71                         Assert.AreEqual ("vb", _codeProvider.FileExtension, "#JW10");\r
72                 }\r
73 \r
74                 [Test]\r
75                 public void LanguageOptionsTest ()\r
76                 {\r
77                         Assert.AreEqual (LanguageOptions.CaseInsensitive, _codeProvider.LanguageOptions, "#JW20");\r
78                 }\r
79 \r
80                 [Test]\r
81                 public void CreateCompiler ()\r
82                 {\r
83                         // Prepare the compilation\r
84                         ICodeCompiler codeCompiler = _codeProvider.CreateCompiler ();\r
85                         Assert.IsNotNull (codeCompiler, "#JW30 - CreateCompiler");\r
86 \r
87                         CompilerParameters options = new CompilerParameters ();\r
88                         options.GenerateExecutable = true;\r
89                         options.IncludeDebugInformation = true;\r
90                         options.TreatWarningsAsErrors = true;\r
91 \r
92                         // process compilation\r
93                         CompilerResults compilerResults = codeCompiler.CompileAssemblyFromSource (options,\r
94                                 "public class TestModule" + Environment.NewLine + "public shared sub Main()"\r
95                                 + Environment.NewLine + "System.Console.Write(\"Hello world!\")"\r
96                                 + Environment.NewLine + "End Sub" + Environment.NewLine + "End Class");\r
97 \r
98                         // Analyse the compilation success/messages\r
99                         StringCollection MyOutput = compilerResults.Output;\r
100                         string MyOutStr = "";\r
101                         foreach (string MyStr in MyOutput) {\r
102                                 MyOutStr += MyStr + Environment.NewLine + Environment.NewLine;\r
103                         }\r
104 \r
105                         if (compilerResults.Errors.Count != 0) {\r
106                                 Assert.Fail ("#JW31 - Hello world compilation: " + MyOutStr);\r
107                         }\r
108 \r
109                         try {\r
110                                 Assembly MyAss = compilerResults.CompiledAssembly;\r
111                         } catch (Exception ex) {\r
112                                 Assert.Fail ("#JW32 - compilerResults.CompiledAssembly hasn't been an expected object" +\r
113                                                 Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace);\r
114                         }\r
115 \r
116                         // Execute the test app\r
117                         ProcessStartInfo NewProcInfo = new ProcessStartInfo ();\r
118                         if (Windows) {\r
119                                 NewProcInfo.FileName = compilerResults.CompiledAssembly.Location;\r
120                         } else {\r
121                                 NewProcInfo.FileName = "mono";\r
122                                 NewProcInfo.Arguments = compilerResults.CompiledAssembly.Location;\r
123                         }\r
124                         NewProcInfo.RedirectStandardOutput = true;\r
125                         NewProcInfo.UseShellExecute = false;\r
126                         NewProcInfo.CreateNoWindow = true;\r
127                         string TestAppOutput = "";\r
128                         try {\r
129                                 Process MyProc = Process.Start (NewProcInfo);\r
130                                 MyProc.WaitForExit ();\r
131                                 TestAppOutput = MyProc.StandardOutput.ReadToEnd ();\r
132                                 MyProc.Close ();\r
133                                 MyProc.Dispose ();\r
134                         } catch (Exception ex) {\r
135                                 Assert.Fail ("#JW34 - " + ex.Message + Environment.NewLine + ex.StackTrace);\r
136                         }\r
137                         Assert.AreEqual ("Hello world!", TestAppOutput, "#JW33 - Application output");\r
138 \r
139                         // Clean up\r
140                         try {\r
141                                 File.Delete (NewProcInfo.FileName);\r
142                         } catch { }\r
143                 }\r
144 \r
145                 [Test]\r
146                 public void CreateGenerator ()\r
147                 {\r
148                         ICodeGenerator MyVBCodeGen;\r
149                         MyVBCodeGen = _codeProvider.CreateGenerator ();\r
150                         Assert.IsNotNull (MyVBCodeGen, "#JW40 - CreateGenerator");\r
151                         Assert.IsTrue (MyVBCodeGen.Supports (GeneratorSupport.DeclareEnums), "#JW41");\r
152                 }\r
153 \r
154                 [Test]\r
155                 public void CompileFromFile_InMemory ()\r
156                 {\r
157                         // create vb source file\r
158                         string sourceFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
159                         using (FileStream f = new FileStream (sourceFile, FileMode.Create)) {\r
160                                 using (StreamWriter s = new StreamWriter (f)) {\r
161                                         s.Write (_sourceTest1);\r
162                                         s.Close ();\r
163                                 }\r
164                                 f.Close ();\r
165                         }\r
166 \r
167                         CompilerParameters options = new CompilerParameters ();\r
168                         options.GenerateExecutable = false;\r
169                         options.GenerateInMemory = true;\r
170                         options.TempFiles = new TempFileCollection (_tempDir);\r
171 \r
172                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();\r
173                         CompilerResults results = compiler.CompileAssemblyFromFile (options,\r
174                                 sourceFile);\r
175 \r
176                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");\r
177                         Assert.IsNull (results.PathToAssembly, "#2");\r
178                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test1"), "#3");\r
179 \r
180                         // verify we don't cleanup files in temp directory too agressively\r
181                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
182 \r
183                         foreach (string file in tempFiles) {\r
184                                 if (file != sourceFile) {\r
185                                         Assert.Fail ("TEMPFILE: " + file);\r
186                                 }\r
187                         }\r
188 \r
189                         Assert.AreEqual (1, tempFiles.Length, "#4");\r
190                         Assert.AreEqual (sourceFile, tempFiles[0], "#5");\r
191 \r
192                 }\r
193 \r
194                 [Test]\r
195                 public void CompileFromFileBatch_InMemory ()\r
196                 {\r
197                         // create vb source file\r
198                         string sourceFile1 = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
199                         using (FileStream f = new FileStream (sourceFile1, FileMode.Create)) {\r
200                                 using (StreamWriter s = new StreamWriter (f)) {\r
201                                         s.Write (_sourceTest1);\r
202                                         s.Close ();\r
203                                 }\r
204                                 f.Close ();\r
205                         }\r
206 \r
207                         string sourceFile2 = Path.Combine (_tempDir, "file2." + _codeProvider.FileExtension);\r
208                         using (FileStream f = new FileStream (sourceFile2, FileMode.Create)) {\r
209                                 using (StreamWriter s = new StreamWriter (f)) {\r
210                                         s.Write (_sourceTest2);\r
211                                         s.Close ();\r
212                                 }\r
213                                 f.Close ();\r
214                         }\r
215 \r
216                         CompilerParameters options = new CompilerParameters ();\r
217                         options.GenerateExecutable = false;\r
218                         options.GenerateInMemory = true;\r
219                         options.TempFiles = new TempFileCollection (_tempDir);\r
220 \r
221                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();\r
222                         CompilerResults results = compiler.CompileAssemblyFromFileBatch (options,\r
223                                 new string[] { sourceFile1, sourceFile2 });\r
224 \r
225                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");\r
226                         Assert.IsNull (results.PathToAssembly, "#2");\r
227 \r
228                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test1"), "#3");\r
229                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test2"), "#4");\r
230 \r
231                         // verify we don't cleanup files in temp directory too agressively\r
232                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
233                         Assert.AreEqual (2, tempFiles.Length, "#5");\r
234                         Assert.IsTrue (File.Exists (sourceFile1), "#6");\r
235                         Assert.IsTrue (File.Exists (sourceFile2), "#7");\r
236                 }\r
237 \r
238                 [Test]\r
239                 public void CompileFromSource_InMemory ()\r
240                 {\r
241                         // create a file in temp directory to ensure that compiler is not removing\r
242                         // too much (temporary) files\r
243                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
244                         using (FileStream fs = File.Create (tempFile)) {\r
245                                 fs.Close ();\r
246                         }\r
247 \r
248                         CompilerParameters options = new CompilerParameters ();\r
249                         options.GenerateExecutable = false;\r
250                         options.GenerateInMemory = true;\r
251                         options.TempFiles = new TempFileCollection (_tempDir);\r
252 \r
253                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();\r
254                         CompilerResults results = compiler.CompileAssemblyFromSource (options,\r
255                                 _sourceTest1);\r
256 \r
257                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");\r
258                         Assert.IsNull (results.PathToAssembly, "#2");\r
259                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test1"), "#3");\r
260 \r
261                         // verify we don't cleanup files in temp directory too agressively\r
262                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
263                         Assert.AreEqual (1, tempFiles.Length, "#4");\r
264                         Assert.AreEqual (tempFile, tempFiles[0], "#5");\r
265                 }\r
266 \r
267                 [Test]\r
268                 public void CompileFromSourceBatch_InMemory ()\r
269                 {\r
270                         // create a file in temp directory to ensure that compiler is not removing\r
271                         // too much (temporary) files\r
272                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
273                         using (FileStream fs = File.Create (tempFile)) {\r
274                                 fs.Close ();\r
275                         }\r
276 \r
277                         CompilerParameters options = new CompilerParameters ();\r
278                         options.GenerateExecutable = false;\r
279                         options.GenerateInMemory = true;\r
280                         options.TempFiles = new TempFileCollection (_tempDir);\r
281 \r
282                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();\r
283                         CompilerResults results = compiler.CompileAssemblyFromSourceBatch (options,\r
284                                 new string[] { _sourceTest1, _sourceTest2 });\r
285 \r
286                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");\r
287                         Assert.IsNull (results.PathToAssembly, "#2");\r
288 \r
289                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test1"), "#3");\r
290                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test2"), "#4");\r
291 \r
292                         // verify we don't cleanup files in temp directory too agressively\r
293                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
294                         Assert.AreEqual (1, tempFiles.Length, "#5");\r
295                         Assert.AreEqual (tempFile, tempFiles[0], "#6");\r
296                 }\r
297 \r
298                 [Test]\r
299                 public void CompileFromDom_NotInMemory ()\r
300                 {\r
301                         // create a file in temp directory to ensure that compiler is not removing\r
302                         // too much (temporary) files\r
303                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
304                         using (FileStream fs = File.Create (tempFile)) {\r
305                                 fs.Close ();\r
306                         }\r
307 \r
308                         // compile and verify result in separate appdomain to avoid file locks\r
309                         AppDomain testDomain = CreateTestDomain ();\r
310                         CrossDomainTester compileTester = CreateCrossDomainTester (testDomain);\r
311 \r
312                         string outputAssembly = null;\r
313 \r
314                         try {\r
315                                 outputAssembly = compileTester.CompileAssemblyFromDom (_tempDir);\r
316                         } finally {\r
317                                 AppDomain.Unload (testDomain);\r
318                         }\r
319 \r
320                         // there should be two files in temp dir: temp file and output assembly\r
321                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
322                         Assert.AreEqual (2, tempFiles.Length, "#1");\r
323                         Assert.IsTrue (File.Exists (outputAssembly), "#2");\r
324                         Assert.IsTrue (File.Exists (tempFile), "#3");\r
325                 }\r
326 \r
327                 [Test]\r
328                 public void CompileFromDomBatch_NotInMemory ()\r
329                 {\r
330                         // create a file in temp directory to ensure that compiler is not removing\r
331                         // too much (temporary) files\r
332                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
333                         using (FileStream fs = File.Create (tempFile)) {\r
334                                 fs.Close ();\r
335                         }\r
336 \r
337                         // compile and verify result in separate appdomain to avoid file locks\r
338                         AppDomain testDomain = CreateTestDomain ();\r
339                         CrossDomainTester compileTester = CreateCrossDomainTester (testDomain);\r
340 \r
341                         string outputAssembly = null;\r
342 \r
343                         try {\r
344                                 outputAssembly = compileTester.CompileAssemblyFromDomBatch (_tempDir);\r
345                         } finally {\r
346                                 AppDomain.Unload (testDomain);\r
347                         }\r
348 \r
349                         // there should be two files in temp dir: temp file and output assembly\r
350                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
351                         Assert.AreEqual (2, tempFiles.Length, "#1");\r
352                         Assert.IsTrue (File.Exists (outputAssembly), "#2");\r
353                         Assert.IsTrue (File.Exists (tempFile), "#3");\r
354                 }\r
355 \r
356                 [Test]\r
357                 public void CompileFromDom_InMemory ()\r
358                 {\r
359                         // create a file in temp directory to ensure that compiler is not removing\r
360                         // too much (temporary) files\r
361                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
362                         using (FileStream fs = File.Create (tempFile)) {\r
363                                 fs.Close ();\r
364                         }\r
365 \r
366                         CompilerParameters options = new CompilerParameters ();\r
367                         options.GenerateExecutable = false;\r
368                         options.GenerateInMemory = true;\r
369                         options.TempFiles = new TempFileCollection (_tempDir);\r
370 \r
371                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();\r
372                         CompilerResults results = compiler.CompileAssemblyFromDom (options, new CodeCompileUnit ());\r
373 \r
374                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");\r
375                         Assert.IsNull (results.PathToAssembly, "#2");\r
376 \r
377                         // verify we don't cleanup files in temp directory too agressively\r
378                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
379                         Assert.AreEqual (1, tempFiles.Length, "#3");\r
380                         Assert.AreEqual (tempFile, tempFiles[0], "#4");\r
381                 }\r
382 \r
383                 [Test]\r
384                 public void CompileFromDomBatch_InMemory ()\r
385                 {\r
386                         // create a file in temp directory to ensure that compiler is not removing\r
387                         // too much (temporary) files\r
388                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);\r
389                         using (FileStream fs = File.Create (tempFile)) {\r
390                                 fs.Close ();\r
391                         }\r
392 \r
393                         CompilerParameters options = new CompilerParameters ();\r
394                         options.GenerateExecutable = false;\r
395                         options.GenerateInMemory = true;\r
396                         options.TempFiles = new TempFileCollection (_tempDir);\r
397 \r
398                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();\r
399                         CompilerResults results = compiler.CompileAssemblyFromDomBatch (options,\r
400                                 new CodeCompileUnit[] { new CodeCompileUnit (), new CodeCompileUnit () });\r
401 \r
402                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");\r
403                         Assert.IsNull (results.PathToAssembly, "#2");\r
404 \r
405                         // verify we don't cleanup files in temp directory too agressively\r
406                         string[] tempFiles = Directory.GetFiles (_tempDir);\r
407                         Assert.AreEqual (1, tempFiles.Length, "#3");\r
408                         Assert.AreEqual (tempFile, tempFiles[0], "#4");\r
409                 }\r
410 \r
411                 //TODO: [Test]\r
412                 public void CreateParser ()\r
413                 {\r
414                         //System.CodeDom.Compiler.ICodeParser CreateParser()\r
415                 }\r
416 \r
417                 //TODO: [Test]\r
418                 public void CreateObjRef ()\r
419                 {\r
420                         //System.Runtime.Remoting.ObjRef CreateObjRef(System.Type requestedType)\r
421                 }\r
422 \r
423                 bool Windows\r
424                 {\r
425                         get {\r
426                                 return OS == OsType.Windows;\r
427                         }\r
428                 }\r
429 \r
430                 bool Unix\r
431                 {\r
432                         get {\r
433                                 return OS == OsType.Unix;\r
434                         }\r
435                 }\r
436 \r
437                 bool Mac\r
438                 {\r
439                         get {\r
440                                 return OS == OsType.Mac;\r
441                         }\r
442                 }\r
443 \r
444                 private static string CreateTempDirectory ()\r
445                 {\r
446                         // create a uniquely named zero-byte file\r
447                         string tempFile = Path.GetTempFileName ();\r
448                         // remove the temporary file\r
449                         File.Delete (tempFile);\r
450                         // create a directory named after the unique temporary file\r
451                         Directory.CreateDirectory (tempFile);\r
452                         // return the path to the temporary directory\r
453                         return tempFile;\r
454                 }\r
455 \r
456                 private static void RemoveDirectory (string path)\r
457                 {\r
458                         try {\r
459                                 if (Directory.Exists (path)) {\r
460                                         string[] directoryNames = Directory.GetDirectories (path);\r
461                                         foreach (string directoryName in directoryNames) {\r
462                                                 RemoveDirectory (directoryName);\r
463                                         }\r
464                                         string[] fileNames = Directory.GetFiles (path);\r
465                                         foreach (string fileName in fileNames) {\r
466                                                 File.Delete (fileName);\r
467                                         }\r
468                                         Directory.Delete (path, true);\r
469                                 }\r
470                         } catch (Exception ex) {\r
471                                 throw new AssertionException ("Unable to cleanup '" + path + "'.", ex);\r
472                         }\r
473                 }\r
474 \r
475                 private static AppDomain CreateTestDomain ()\r
476                 {\r
477                         return AppDomain.CreateDomain ("CompileFromDom", AppDomain.CurrentDomain.Evidence,\r
478                                 AppDomain.CurrentDomain.SetupInformation);\r
479                 }\r
480 \r
481                 private static CrossDomainTester CreateCrossDomainTester (AppDomain domain)\r
482                 {\r
483                         Type testerType = typeof (CrossDomainTester);\r
484 \r
485                         return (CrossDomainTester) domain.CreateInstanceAndUnwrap (\r
486                                 testerType.Assembly.FullName, testerType.FullName, false,\r
487                                 BindingFlags.Public | BindingFlags.Instance, null, new object[0],\r
488                                 CultureInfo.InvariantCulture, new object[0], domain.Evidence);\r
489                 }\r
490 \r
491                 private class CrossDomainTester : MarshalByRefObject\r
492                 {\r
493                         public string CompileAssemblyFromDom (string tempDir)\r
494                         {\r
495                                 CompilerParameters options = new CompilerParameters ();\r
496                                 options.GenerateExecutable = false;\r
497                                 options.GenerateInMemory = false;\r
498                                 options.TempFiles = new TempFileCollection (tempDir);\r
499 \r
500                                 VBCodeProvider codeProvider = new VBCodeProvider ();\r
501                                 ICodeCompiler compiler = codeProvider.CreateCompiler ();\r
502                                 CompilerResults results = compiler.CompileAssemblyFromDom (options, new CodeCompileUnit ());\r
503 \r
504                                 Assert.IsTrue (results.CompiledAssembly.Location.Length != 0,\r
505                                         "Location should not be empty string");\r
506                                 Assert.IsNotNull (results.PathToAssembly, "PathToAssembly should not be null");\r
507 \r
508                                 return results.PathToAssembly;\r
509                         }\r
510 \r
511                         public string CompileAssemblyFromDomBatch (string tempDir)\r
512                         {\r
513                                 CompilerParameters options = new CompilerParameters ();\r
514                                 options.GenerateExecutable = false;\r
515                                 options.GenerateInMemory = false;\r
516                                 options.TempFiles = new TempFileCollection (tempDir);\r
517 \r
518                                 VBCodeProvider codeProvider = new VBCodeProvider ();\r
519                                 ICodeCompiler compiler = codeProvider.CreateCompiler ();\r
520                                 CompilerResults results = compiler.CompileAssemblyFromDomBatch (options, new CodeCompileUnit[] { new CodeCompileUnit (), new CodeCompileUnit () });\r
521 \r
522                                 Assert.IsTrue (results.CompiledAssembly.Location.Length != 0,\r
523                                         "Location should not be empty string");\r
524                                 Assert.IsNotNull (results.PathToAssembly, "PathToAssembly should not be null");\r
525 \r
526                                 return results.PathToAssembly;\r
527                         }\r
528                 }\r
529         }\r
530 }\r