Merge pull request #2231 from ludovic-henry/coop-sync-friendliness
[mono.git] / mcs / class / System / Test / Microsoft.CSharp / CSharpCodeProviderTest.cs
1 //
2 // Microsoft.CSharp.CSharpCodeProviderTest.cs
3 //
4 // Author:
5 // Gert Driesen (drieseng@users.sourceforge.net)
6 //
7 // (C) 2005 Novell
8 //
9
10 using System;
11 using System.CodeDom;
12 using System.CodeDom.Compiler;
13 using System.Collections.Specialized;
14 using System.Globalization;
15 using System.IO;
16 using System.Reflection;
17 using Microsoft.CSharp;
18 using NUnit.Framework;
19
20 namespace MonoTests.Microsoft.CSharp
21 {
22         [TestFixture]
23         public class CSharpCodeProviderTest
24         {
25                 private string _tempDir;
26                 private CodeDomProvider _codeProvider;
27
28                 private static readonly string _sourceLibrary1 = "public class Test1 {}";
29                 private static readonly string _sourceLibrary2 = "public class Test2 {}";
30                 private static readonly string _sourceLibrary3 =
31                         @"public class Test3 { public void F() { } }
32                         public class Test4 : Test3 { public void F() { } }";
33                 private static readonly string _sourceExecutable = "public class Program { static void Main () { } }";
34
35                 [SetUp]
36                 public void SetUp ()
37                 {
38                         _codeProvider = new CSharpCodeProvider ();
39                         _tempDir = CreateTempDirectory ();
40                 }
41
42                 [TearDown]
43                 public void TearDown ()
44                 {
45                         RemoveDirectory (_tempDir);
46                 }
47
48                 [Test]
49                 public void FileExtension ()
50                 {
51                         Assert.AreEqual ("cs", _codeProvider.FileExtension);
52                 }
53
54                 [Test]
55                 public void LanguageOptionsTest ()
56                 {
57                         Assert.AreEqual (LanguageOptions.None, _codeProvider.LanguageOptions);
58                 }
59
60                 [Test]
61                 public void GeneratorSupports ()
62                 {
63                         ICodeGenerator codeGenerator = _codeProvider.CreateGenerator ();
64                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareEnums), "#1");
65                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.ArraysOfArrays), "#2");
66                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.AssemblyAttributes), "#3");
67                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.ChainedConstructorArguments), "#4");
68                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.ComplexExpressions), "#5");
69                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareDelegates), "#6");
70                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareEnums), "#7");
71                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareEvents), "#8");
72                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareInterfaces), "#9");
73                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareValueTypes), "#10");
74                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.EntryPointMethod), "#11");
75                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.GotoStatements), "#12");
76                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.MultidimensionalArrays), "#13");
77                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.MultipleInterfaceMembers), "#14");
78                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.NestedTypes), "#15");
79                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.ParameterAttributes), "#16");
80                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.PublicStaticMembers), "#17");
81                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.ReferenceParameters), "#18");
82                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.ReturnTypeAttributes), "#19");
83                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.StaticConstructors), "#20");
84                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.TryCatchStatements), "#21");
85                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.Win32Resources), "#22");
86                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.DeclareIndexerProperties), "#23");
87                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.GenericTypeDeclaration), "#24");
88                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.GenericTypeReference), "#25");
89                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.PartialTypes), "#26");
90                         Assert.IsTrue (codeGenerator.Supports (GeneratorSupport.Resources), "#27");
91                 }
92
93                 [Test]
94                 public void CompileFromFile_InMemory ()
95                 {
96                         // create source file
97                         string sourceFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
98                         using (FileStream f = new FileStream (sourceFile, FileMode.Create)) {
99                                 using (StreamWriter s = new StreamWriter (f)) {
100                                         s.Write (_sourceLibrary1);
101                                         s.Close ();
102                                 }
103                                 f.Close ();
104                         }
105
106                         CompilerParameters options = new CompilerParameters ();
107                         options.GenerateExecutable = false;
108                         options.GenerateInMemory = true;
109                         options.TempFiles = new TempFileCollection (_tempDir);
110                         options.EmbeddedResources.Add (sourceFile);
111
112                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
113                         CompilerResults results = compiler.CompileAssemblyFromFile (options,
114                                 sourceFile);
115
116                         // verify compilation was successful
117                         AssertCompileResults (results, true);
118
119                         Assembly compiledAssembly = results.CompiledAssembly;
120
121                         Assert.IsNotNull (compiledAssembly, "#1");
122                         Assert.AreEqual (string.Empty, compiledAssembly.Location, "#2");
123                         Assert.IsNull (results.PathToAssembly, "#3");
124                         Assert.IsNotNull (compiledAssembly.GetType ("Test1"), "#4");
125                         
126                         // verify we don't cleanup files in temp directory too agressively
127                         string[] tempFiles = Directory.GetFiles (_tempDir);
128                         Assert.AreEqual (1, tempFiles.Length, "#5");
129                         Assert.AreEqual (sourceFile, tempFiles[0], "#6");
130                         
131                         string[] resources = compiledAssembly.GetManifestResourceNames();
132                         Assert.IsNotNull (resources, "#7");
133                         Assert.AreEqual (1, resources.Length, "#8");
134                         Assert.AreEqual ("file.cs", resources[0], "#9");
135                         Assert.IsNull (compiledAssembly.GetFile ("file.cs"), "#10");
136                         Assert.IsNotNull (compiledAssembly.GetManifestResourceStream  ("file.cs"), "#11");
137                         ManifestResourceInfo info = compiledAssembly.GetManifestResourceInfo ("file.cs");
138                         Assert.IsNotNull (info, "#12");
139                         Assert.IsNull (info.FileName, "#13");
140                         Assert.IsNull (info.ReferencedAssembly, "#14");
141                         Assert.AreEqual ((ResourceLocation.Embedded | ResourceLocation.ContainedInManifestFile), info.ResourceLocation, "#15");
142                 }
143
144                 [Test]
145                 public void CompileFromFileBatch_Executable_InMemory ()
146                 {
147                         // create source file
148                         string sourceFile1 = Path.Combine (_tempDir, "file1." + _codeProvider.FileExtension);
149                         using (FileStream f = new FileStream (sourceFile1, FileMode.Create)) {
150                                 using (StreamWriter s = new StreamWriter (f)) {
151                                         s.Write (_sourceLibrary1);
152                                         s.Close ();
153                                 }
154                                 f.Close ();
155                         }
156
157                         string sourceFile2 = Path.Combine (_tempDir, "file2." + _codeProvider.FileExtension);
158                         using (FileStream f = new FileStream (sourceFile2, FileMode.Create)) {
159                                 using (StreamWriter s = new StreamWriter (f)) {
160                                         s.Write (_sourceExecutable);
161                                         s.Close ();
162                                 }
163                                 f.Close ();
164                         }
165
166                         CompilerParameters options = new CompilerParameters ();
167                         options.GenerateExecutable = true;
168                         options.GenerateInMemory = true;
169                         options.OutputAssembly = string.Empty;
170                         options.TempFiles = new TempFileCollection (_tempDir);
171                         options.EmbeddedResources.Add (sourceFile1);
172                         options.LinkedResources.Add (sourceFile2);
173
174                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
175                         CompilerResults results = compiler.CompileAssemblyFromFileBatch (options,
176                                 new string [] { sourceFile1, sourceFile2 });
177
178                         // verify compilation was successful
179                         AssertCompileResults (results, true);
180
181                         Assembly compiledAssembly = results.CompiledAssembly;
182
183                         Assert.IsNotNull (compiledAssembly, "#A1");
184                         Assert.AreEqual (string.Empty, compiledAssembly.Location, "#A2");
185                         Assert.IsNull (results.PathToAssembly, "#A3");
186                         Assert.IsNotNull (options.OutputAssembly, "#A4");
187                         Assert.AreEqual (".exe", Path.GetExtension (options.OutputAssembly), "#A5");
188                         Assert.AreEqual (_tempDir, Path.GetDirectoryName (options.OutputAssembly), "#A6");
189                         Assert.IsFalse (File.Exists (options.OutputAssembly), "#A7");
190
191                         Assert.IsNotNull (compiledAssembly.GetType ("Test1"), "#B1");
192                         Assert.IsNotNull (compiledAssembly.GetType ("Program"), "#B2");
193
194                         // verify we don't cleanup files in temp directory too agressively
195                         string [] tempFiles = Directory.GetFiles (_tempDir);
196                         Assert.AreEqual (2, tempFiles.Length, "#C1");
197                         Assert.IsTrue (File.Exists (sourceFile1), "#C2");
198                         Assert.IsTrue (File.Exists (sourceFile2), "#C3");
199
200                         string[] resources = compiledAssembly.GetManifestResourceNames();
201                         Assert.IsNotNull (resources, "#D1");
202                         Assert.AreEqual (2, resources.Length, "#D2");
203
204                         Assert.IsTrue (resources[0] == "file1.cs" || resources [0] == "file2.cs", "#E1");
205                         Assert.IsNull (compiledAssembly.GetFile ("file1.cs"), "#E2");
206                         Assert.IsNotNull (compiledAssembly.GetManifestResourceStream  ("file1.cs"), "#E3");
207                         ManifestResourceInfo info = compiledAssembly.GetManifestResourceInfo ("file1.cs");
208                         Assert.IsNotNull (info, "#E4");
209                         Assert.IsNull (info.FileName, "#E5");
210                         Assert.IsNull (info.ReferencedAssembly, "#E6");
211                         Assert.AreEqual ((ResourceLocation.Embedded | ResourceLocation.ContainedInManifestFile), info.ResourceLocation, "#E7");
212
213                         Assert.IsTrue (resources[1] == "file1.cs" || resources [1] == "file2.cs", "#F1");
214                         try {
215                                 compiledAssembly.GetFile ("file2.cs");
216                                 Assert.Fail ("#F2");
217                         } catch (FileNotFoundException) {
218                         }
219                         try {
220                                 compiledAssembly.GetManifestResourceStream  ("file2.cs");
221                                 Assert.Fail ("#F3");
222                         } catch (FileNotFoundException) {
223                         }
224                         info = compiledAssembly.GetManifestResourceInfo ("file2.cs");
225                         Assert.IsNotNull (info, "#F4");
226                         Assert.IsNotNull (info.FileName, "#F5");
227                         Assert.AreEqual ("file2.cs", info.FileName, "#F6");
228                         Assert.IsNull (info.ReferencedAssembly, "#F7");
229                         Assert.AreEqual ((ResourceLocation) 0, info.ResourceLocation, "#F8");
230                 }
231
232                 [Test]
233                 public void CompileFromFileBatch_Library_InMemory ()
234                 {
235                         // create source file
236                         string sourceFile1 = Path.Combine (_tempDir, "file1." + _codeProvider.FileExtension);
237                         using (FileStream f = new FileStream (sourceFile1, FileMode.Create)) {
238                                 using (StreamWriter s = new StreamWriter (f)) {
239                                         s.Write (_sourceLibrary1);
240                                         s.Close ();
241                                 }
242                                 f.Close ();
243                         }
244
245                         string sourceFile2 = Path.Combine (_tempDir, "file2." + _codeProvider.FileExtension);
246                         using (FileStream f = new FileStream (sourceFile2, FileMode.Create)) {
247                                 using (StreamWriter s = new StreamWriter (f)) {
248                                         s.Write (_sourceLibrary2);
249                                         s.Close ();
250                                 }
251                                 f.Close ();
252                         }
253
254                         CompilerParameters options = new CompilerParameters ();
255                         options.GenerateExecutable = false;
256                         options.GenerateInMemory = true;
257                         options.TempFiles = new TempFileCollection (_tempDir);
258                         options.EmbeddedResources.Add (sourceFile1);
259                         options.LinkedResources.Add (sourceFile2);
260
261                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
262                         CompilerResults results = compiler.CompileAssemblyFromFileBatch (options,
263                                 new string [] { sourceFile1, sourceFile2 });
264
265                         // verify compilation was successful
266                         AssertCompileResults (results, true);
267
268                         Assembly compiledAssembly = results.CompiledAssembly;
269
270                         Assert.IsNotNull (compiledAssembly, "#A1");
271                         Assert.AreEqual (string.Empty, compiledAssembly.Location, "#A2");
272                         Assert.IsNull (results.PathToAssembly, "#A3");
273                         Assert.IsNotNull (options.OutputAssembly, "#A4");
274                         Assert.AreEqual (".dll", Path.GetExtension (options.OutputAssembly), "#A5");
275                         Assert.AreEqual (_tempDir, Path.GetDirectoryName (options.OutputAssembly), "#A6");
276                         Assert.IsFalse (File.Exists (options.OutputAssembly), "#A7");
277
278                         Assert.IsNotNull (compiledAssembly.GetType ("Test1"), "#B1");
279                         Assert.IsNotNull (compiledAssembly.GetType ("Test2"), "#B2");
280
281                         // verify we don't cleanup files in temp directory too agressively
282                         string [] tempFiles = Directory.GetFiles (_tempDir);
283                         Assert.AreEqual (2, tempFiles.Length, "#C1");
284                         Assert.IsTrue (File.Exists (sourceFile1), "#C2");
285                         Assert.IsTrue (File.Exists (sourceFile2), "#C3");
286
287                         string[] resources = compiledAssembly.GetManifestResourceNames();
288                         Assert.IsNotNull (resources, "#D1");
289                         Assert.AreEqual (2, resources.Length, "#D2");
290
291                         Assert.IsTrue (resources[0] == "file1.cs" || resources [0] == "file2.cs", "#E1");
292                         Assert.IsNull (compiledAssembly.GetFile ("file1.cs"), "#E2");
293                         Assert.IsNotNull (compiledAssembly.GetManifestResourceStream  ("file1.cs"), "#E3");
294                         ManifestResourceInfo info = compiledAssembly.GetManifestResourceInfo ("file1.cs");
295                         Assert.IsNotNull (info, "#E4");
296                         Assert.IsNull (info.FileName, "#E5");
297                         Assert.IsNull (info.ReferencedAssembly, "#E6");
298                         Assert.AreEqual ((ResourceLocation.Embedded | ResourceLocation.ContainedInManifestFile), info.ResourceLocation, "#E7");
299
300                         Assert.IsTrue (resources[1] == "file1.cs" || resources [1] == "file2.cs", "#F1");
301                         try {
302                                 compiledAssembly.GetFile ("file2.cs");
303                                 Assert.Fail ("#F2");
304                         } catch (FileNotFoundException) {
305                         }
306                         try {
307                                 compiledAssembly.GetManifestResourceStream  ("file2.cs");
308                                 Assert.Fail ("#F3");
309                         } catch (FileNotFoundException) {
310                         }
311                         info = compiledAssembly.GetManifestResourceInfo ("file2.cs");
312                         Assert.IsNotNull (info, "#F4");
313                         Assert.IsNotNull (info.FileName, "#F5");
314                         Assert.AreEqual ("file2.cs", info.FileName, "#F6");
315                         Assert.IsNull (info.ReferencedAssembly, "#F7");
316                         Assert.AreEqual ((ResourceLocation) 0, info.ResourceLocation, "#F8");
317                 }
318
319                 [Test]
320                 public void CompileFromSource_InMemory ()
321                 {
322                         // create a file in temp directory to ensure that compiler is not removing
323                         // too much (temporary) files
324                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
325                         using (FileStream fs = File.Create (tempFile)) {
326                                 fs.Close ();
327                         }
328
329                         CompilerParameters options = new CompilerParameters ();
330                         options.GenerateExecutable = false;
331                         options.GenerateInMemory = true;
332                         options.TempFiles = new TempFileCollection (_tempDir);
333
334                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
335                         CompilerResults results = compiler.CompileAssemblyFromSource (options,
336                                 _sourceLibrary1);
337
338                         // verify compilation was successful
339                         AssertCompileResults (results, true);
340
341                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");
342                         Assert.IsNull (results.PathToAssembly, "#2");
343                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test1"), "#3");
344
345                         // verify we don't cleanup files in temp directory too agressively
346                         string[] tempFiles = Directory.GetFiles (_tempDir);
347                         Assert.AreEqual (1, tempFiles.Length, "#4");
348                         Assert.AreEqual (tempFile, tempFiles[0], "#5");
349                 }
350
351                 [Test]
352                 public void CompileFromSource_InMemory_Twice ()
353                 {
354                         CompilerParameters options = new CompilerParameters ();
355                         options.GenerateExecutable = false;
356                         options.GenerateInMemory = true;
357
358                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
359
360                         var src_1 = "class X { ";
361
362                         CompilerResults results_1 = compiler.CompileAssemblyFromSource (options, src_1);
363                         var output_1 = options.OutputAssembly;
364
365                         var src_2 = "class X { }";
366
367                         CompilerResults results_2 = compiler.CompileAssemblyFromSource (options, src_2);
368                         var output_2 = options.OutputAssembly;
369
370                         // verify compilation was successful
371                         AssertCompileResults (results_2, true);
372
373                         Assert.AreEqual (output_1, output_2, "#1");
374                 }
375
376
377                 [Test]
378                 public void CompileFromSource_InMemory_With_Extra_Delete ()
379                 {
380                         CompilerParameters options = new CompilerParameters ();
381                         options.GenerateExecutable = false;
382                         options.GenerateInMemory = true;
383
384                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
385
386                         var src_1 = "class X { ";
387
388                         compiler.CompileAssemblyFromSource (options, src_1);
389
390                         options.TempFiles.Delete ();
391                         options.TempFiles.Delete ();
392                 }
393
394                 [Test]
395                 public void CompileFromSourceBatch_InMemory ()
396                 {
397                         // create a file in temp directory to ensure that compiler is not removing
398                         // too much (temporary) files
399                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
400                         using (FileStream fs = File.Create (tempFile)) {
401                                 fs.Close ();
402                         }
403
404                         string outputAssembly = Path.Combine (_tempDir, "sourcebatch.dll");
405
406                         CompilerParameters options = new CompilerParameters ();
407                         options.GenerateExecutable = false;
408                         options.GenerateInMemory = true;
409                         options.OutputAssembly = outputAssembly;
410                         options.TempFiles = new TempFileCollection (_tempDir);
411
412                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
413                         CompilerResults results = compiler.CompileAssemblyFromSourceBatch (options,
414                                 new string [] { _sourceLibrary1, _sourceLibrary2 });
415
416                         // verify compilation was successful
417                         AssertCompileResults (results, true);
418
419                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#A1");
420                         Assert.IsNull (results.PathToAssembly, "#A2");
421                         Assert.IsNotNull (options.OutputAssembly, "#A3");
422                         Assert.AreEqual (outputAssembly, options.OutputAssembly, "#A4");
423                         Assert.IsTrue (File.Exists (outputAssembly), "#A5");
424
425                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test1"), "#B1");
426                         Assert.IsNotNull (results.CompiledAssembly.GetType ("Test2"), "#B2");
427
428                         // verify we don't cleanup files in temp directory too agressively
429                         string[] tempFiles = Directory.GetFiles (_tempDir);
430                         Assert.AreEqual (2, tempFiles.Length, "#C1");
431                         Assert.AreEqual (tempFile, tempFiles[0], "#C2");
432                         Assert.AreEqual (outputAssembly, tempFiles [1], "#C3");
433                 }
434
435                 [Test]
436                 public void CompileFromDom_NotInMemory ()
437                 {
438                         // create a file in temp directory to ensure that compiler is not removing
439                         // too much (temporary) files
440                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
441                         using (FileStream fs = File.Create (tempFile)) {
442                                 fs.Close ();
443                         }
444
445                         // compile and verify result in separate appdomain to avoid file locks
446                         AppDomain testDomain = CreateTestDomain ();
447                         CrossDomainTester compileTester = CreateCrossDomainTester (testDomain);
448
449                         string outputAssembly = null;
450
451                         try {
452                                 outputAssembly = compileTester.CompileAssemblyFromDom (_tempDir);
453                         } finally {
454                                 AppDomain.Unload (testDomain);
455                         }
456
457                         // there should be two files in temp dir: temp file and output assembly
458                         string[] tempFiles = Directory.GetFiles (_tempDir);
459                         Assert.AreEqual (2, tempFiles.Length, "#1");
460                         Assert.IsTrue (File.Exists (outputAssembly), "#2");
461                         Assert.IsTrue (File.Exists (tempFile), "#3");
462                 }
463
464                 [Test]
465                 public void CompileFromDomBatch_NotInMemory ()
466                 {
467                         // create a file in temp directory to ensure that compiler is not removing
468                         // too much (temporary) files
469                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
470                         using (FileStream fs = File.Create (tempFile)) {
471                                 fs.Close ();
472                         }
473
474                         // compile and verify result in separate appdomain to avoid file locks
475                         AppDomain testDomain = CreateTestDomain ();
476                         CrossDomainTester compileTester = CreateCrossDomainTester (testDomain);
477
478                         string outputAssembly = null;
479                         try {
480                                 outputAssembly = compileTester.CompileAssemblyFromDomBatch (_tempDir);
481                         } finally {
482                                 AppDomain.Unload (testDomain);
483                         }
484
485                         // there should be two files in temp dir: temp file and output assembly
486                         string[] tempFiles = Directory.GetFiles (_tempDir);
487                         Assert.AreEqual (2, tempFiles.Length, "#1");
488                         Assert.IsTrue (File.Exists (outputAssembly), "#2");
489                         Assert.IsTrue (File.Exists (tempFile), "#3");
490                 }
491
492                 [Test]
493                 public void CompileFromDom_InMemory ()
494                 {
495                         // create a file in temp directory to ensure that compiler is not removing
496                         // too much (temporary) files
497                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
498                         using (FileStream fs = File.Create (tempFile)) {
499                                 fs.Close ();
500                         }
501
502                         CompilerParameters options = new CompilerParameters ();
503                         options.GenerateExecutable = false;
504                         options.GenerateInMemory = true;
505                         options.TempFiles = new TempFileCollection (_tempDir);
506
507                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
508                         CompilerResults results = compiler.CompileAssemblyFromDom (options, new CodeCompileUnit ());
509
510                         // verify compilation was successful
511                         AssertCompileResults (results, true);
512
513                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");
514                         Assert.IsNull (results.PathToAssembly, "#2");
515
516                         // verify we don't cleanup files in temp directory too agressively
517                         string[] tempFiles = Directory.GetFiles (_tempDir);
518                         Assert.AreEqual (1, tempFiles.Length, "#3");
519                         Assert.AreEqual (tempFile, tempFiles[0], "#4");
520                 }
521
522                 [Test]
523                 public void CompileFromDomBatch_InMemory ()
524                 {
525                         // create a file in temp directory to ensure that compiler is not removing
526                         // too much (temporary) files
527                         string tempFile = Path.Combine (_tempDir, "file." + _codeProvider.FileExtension);
528                         using (FileStream fs = File.Create (tempFile)) {
529                                 fs.Close ();
530                         }
531
532                         CompilerParameters options = new CompilerParameters ();
533                         options.GenerateExecutable = false;
534                         options.GenerateInMemory = true;
535                         options.TempFiles = new TempFileCollection (_tempDir);
536
537                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
538                         CompilerResults results = compiler.CompileAssemblyFromDomBatch (options,
539                                 new CodeCompileUnit[] { new CodeCompileUnit (), new CodeCompileUnit () });
540
541                         // verify compilation was successful
542                         AssertCompileResults (results, true);
543
544                         Assert.AreEqual (string.Empty, results.CompiledAssembly.Location, "#1");
545                         Assert.IsNull (results.PathToAssembly, "#2");
546
547                         // verify we don't cleanup files in temp directory too agressively
548                         string[] tempFiles = Directory.GetFiles (_tempDir);
549                         Assert.AreEqual (1, tempFiles.Length, "#3");
550                         Assert.AreEqual (tempFile, tempFiles[0], "#4");
551                 }
552
553                 [Test]
554                 public void MultiLineWarningIsReportedAsOneWarning()
555                 {
556                         CompilerParameters options = new CompilerParameters ();
557                         options.GenerateExecutable = false;
558                         options.GenerateInMemory = true;
559                         options.TempFiles = new TempFileCollection (_tempDir);
560
561                         ICodeCompiler compiler = _codeProvider.CreateCompiler ();
562                         CompilerResults results = compiler.CompileAssemblyFromSource (options,
563                                 _sourceLibrary3);
564
565                         // verify compilation was successful
566                         AssertCompileResults (results, true);
567                 }
568
569                 private static string CreateTempDirectory ()
570                 {
571                         // create a uniquely named zero-byte file
572                         string tempFile = Path.GetTempFileName ();
573                         // remove the temporary file
574                         File.Delete (tempFile);
575                         // create a directory named after the unique temporary file
576                         Directory.CreateDirectory (tempFile);
577                         // return the path to the temporary directory
578                         return tempFile;
579                 }
580
581                 private static void RemoveDirectory (string path)
582                 {
583                         try {
584                                 if (Directory.Exists (path)) {
585                                         string[] directoryNames = Directory.GetDirectories (path);
586                                         foreach (string directoryName in directoryNames) {
587                                                 RemoveDirectory (directoryName);
588                                         }
589                                         string[] fileNames = Directory.GetFiles (path);
590                                         foreach (string fileName in fileNames) {
591                                                 File.Delete (fileName);
592                                         }
593                                         Directory.Delete (path, true);
594                                 }
595                         } catch (Exception ex) {
596                                 throw new AssertionException ("Unable to cleanup '" + path + "'.", ex);
597                         }
598                 }
599
600                 private static void AssertCompileResults (CompilerResults results, bool allowWarnings)
601                 {
602                         foreach (CompilerError compilerError in results.Errors) {
603                                 if (allowWarnings && compilerError.IsWarning) {
604                                         continue;
605                                 }
606
607                                 throw new Exception (compilerError.ToString ());
608                         }
609                 }
610
611                 private static AppDomain CreateTestDomain ()
612                 {
613                         return AppDomain.CreateDomain ("CompileFromDom", AppDomain.CurrentDomain.Evidence,
614                                 AppDomain.CurrentDomain.SetupInformation);
615                 }
616
617                 private static CrossDomainTester CreateCrossDomainTester (AppDomain domain)
618                 {
619                         Type testerType = typeof (CrossDomainTester);
620
621                         return (CrossDomainTester) domain.CreateInstanceAndUnwrap (
622                                 testerType.Assembly.FullName, testerType.FullName, false,
623                                 BindingFlags.Public | BindingFlags.Instance, null, new object[0],
624                                 CultureInfo.InvariantCulture, new object[0], domain.Evidence);
625                 }
626
627                 // do not use the Assert class as this will introduce failures if the
628                 // nunit.framework assembly is not in the GAC
629                 private class CrossDomainTester : MarshalByRefObject
630                 {
631                         public string CompileAssemblyFromDom (string tempDir)
632                         {
633                                 CompilerParameters options = new CompilerParameters ();
634                                 options.GenerateExecutable = false;
635                                 options.GenerateInMemory = false;
636                                 options.TempFiles = new TempFileCollection (tempDir);
637
638                                 CSharpCodeProvider codeProvider = new CSharpCodeProvider ();
639                                 ICodeCompiler compiler = codeProvider.CreateCompiler ();
640                                 CompilerResults results = compiler.CompileAssemblyFromDom (options, new CodeCompileUnit ());
641
642                                 // verify compilation was successful
643                                 AssertCompileResults (results, true);
644
645                                 if (results.CompiledAssembly.Location.Length == 0)
646                                         throw new Exception ("Location should not be empty string");
647                                 if (results.PathToAssembly == null)
648                                         throw new Exception ("PathToAssembly should not be null");
649
650                                 return results.PathToAssembly;
651                         }
652
653                         public string CompileAssemblyFromDomBatch (string tempDir)
654                         {
655                                 CompilerParameters options = new CompilerParameters ();
656                                 options.GenerateExecutable = false;
657                                 options.GenerateInMemory = false;
658                                 options.TempFiles = new TempFileCollection (tempDir);
659
660                                 CSharpCodeProvider codeProvider = new CSharpCodeProvider ();
661                                 ICodeCompiler compiler = codeProvider.CreateCompiler ();
662                                 CompilerResults results = compiler.CompileAssemblyFromDomBatch (options, new CodeCompileUnit[] { new CodeCompileUnit (), new CodeCompileUnit () });
663
664                                 // verify compilation was successful
665                                 AssertCompileResults (results, true);
666
667                                 if (results.CompiledAssembly.Location.Length == 0)
668                                         throw new Exception ("Location should not be empty string");
669                                 if (results.PathToAssembly == null)
670                                         throw new Exception ("PathToAssembly should not be null");
671
672                                 return results.PathToAssembly;
673                         }
674                 }
675         }
676 }