Add support for ToolsVersion and correctly build msbuild+xbuild assemblies
[mono.git] / mcs / class / Microsoft.Build.Engine / Test / Microsoft.Build.BuildEngine / EngineTest.cs
1 //
2 // EngineTest.cs:
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 using System;
29 using Microsoft.Build.BuildEngine;
30 using Microsoft.Build.Framework;
31 using Microsoft.Build.Utilities;
32 using NUnit.Framework;
33 using System.IO;
34
35 namespace MonoTests.Microsoft.Build.BuildEngine {
36
37         class CheckUnregisterLogger : Logger {
38                 bool anything = false;
39
40                 public override void Initialize (IEventSource eventSource)
41                 {
42                         eventSource.AnyEventRaised += delegate { anything = true; };
43                         eventSource.BuildFinished += delegate { anything = true; };
44                         eventSource.BuildStarted += delegate { anything = true; };
45                         eventSource.CustomEventRaised += delegate { anything = true; };
46                         eventSource.ErrorRaised += delegate { anything = true; };
47                         eventSource.MessageRaised += delegate { anything = true; };
48                         eventSource.ProjectFinished += delegate { anything = true; };
49                         eventSource.ProjectStarted += delegate { anything = true; };
50                         eventSource.StatusEventRaised += delegate { anything = true; };
51                         eventSource.TargetFinished += delegate { anything = true; };
52                         eventSource.TargetStarted += delegate { anything = true; };
53                         eventSource.TaskFinished += delegate { anything = true; };
54                         eventSource.TaskStarted += delegate { anything = true; };
55                         eventSource.WarningRaised += delegate { anything = true; };
56                 }
57
58                 public bool Anything { get { return anything; } }
59         }
60
61         [TestFixture]
62         public class EngineTest {
63
64                 Engine engine;
65                 string secondProject;
66
67                 static string GetPropValue (BuildPropertyGroup bpg, string name)
68                 {
69                         foreach (BuildProperty bp in bpg) {
70                                 if (bp.Name == name) {
71                                         return bp.FinalValue;
72                                 }
73                         }
74                         return String.Empty;
75                 }
76
77                 [SetUp]
78                 public void Setup ()
79                 {
80                         secondProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
81         <PropertyGroup Condition=""'$(foo)' == 'hello'"">
82                 <A>FooWasHello</A>
83         </PropertyGroup>
84         <Target Name=""TargetA"">
85                 <Message Text=""(TargetA) foo: $(foo) A: $(A) External: $(External)""/>
86         </Target>
87
88         <Target Name=""TargetB"">
89                 <Message Text=""(TargetB) foo: $(foo) A: $(A) External: $(External)""/>
90         </Target>
91 </Project>";
92
93                 }
94
95                 [Test]
96                 public void TestCtor ()
97                 {
98                         engine = new Engine (Consts.BinPath);
99                 }
100
101                 // Before a project can be instantiated, Engine.BinPath must be set to the location on disk where MSBuild is installed.
102                 // This is used to evaluate $(MSBuildBinPath).
103                 /* This isn't valid for 3.5
104
105                 [Test]
106                 [ExpectedException (typeof (InvalidOperationException))]
107                 public void TestNewProject ()
108                 {
109                         engine = new Engine ();
110
111                         engine.CreateNewProject ();
112                 }*/
113
114                 [Test]
115                 public void TestBinPath ()
116                 {
117                         engine = new Engine (Consts.BinPath);
118
119                         Assert.AreEqual (Consts.BinPath, engine.BinPath, "A1");
120                 }
121
122                 [Test]
123                 public void TestBuildEnabled ()
124                 {
125                         engine = new Engine (Consts.BinPath);
126
127                         Assert.AreEqual (true, engine.BuildEnabled, "A1");
128                 }
129
130                 [Test]
131                 public void TestOnlyLogCriticalEvents ()
132                 {
133                         engine = new Engine (Consts.BinPath);
134
135                         Assert.AreEqual (false, engine.OnlyLogCriticalEvents, "A1");
136                 }
137
138                 [Test]
139                 public void TestGlobalProperties ()
140                 {
141                         engine = new Engine (Consts.BinPath);
142                         Project project;
143
144                         Assert.IsNotNull (engine.GlobalProperties, "A1");
145                         Assert.AreEqual (0, engine.GlobalProperties.Count, "A2");
146                         Assert.AreEqual (String.Empty, engine.GlobalProperties.Condition, "A3");
147                         Assert.IsFalse (engine.GlobalProperties.IsImported, "A4");
148                         
149                         engine.GlobalProperties.SetProperty ("GlobalA", "value1");
150                         Assert.AreEqual (1, engine.GlobalProperties.Count, "A5");
151                         engine.GlobalProperties.SetProperty ("GlobalB", "value1");
152                         Assert.AreEqual (2, engine.GlobalProperties.Count, "A6");
153                         engine.GlobalProperties.SetProperty ("GlobalA", "value2");
154                         Assert.AreEqual (2, engine.GlobalProperties.Count, "A7");
155
156                         project = engine.CreateNewProject ();
157                         Assert.AreEqual (2, project.GlobalProperties.Count, "A8");
158                         project.GlobalProperties.SetProperty ("GlobalC", "value3");
159                         Assert.AreEqual (3, project.GlobalProperties.Count, "A9");
160                         Assert.AreEqual (2, engine.GlobalProperties.Count, "A10");
161
162                         project.GlobalProperties.SetProperty ("GlobalA", "value3");
163                         Assert.AreEqual ("value2", GetPropValue(engine.GlobalProperties, "GlobalA"), "A11");
164                         engine.GlobalProperties.SetProperty ("GlobalB", "value3");
165                         Assert.AreEqual ("value1", GetPropValue(project.GlobalProperties, "GlobalB"), "A12");
166
167                         engine.GlobalProperties.SetProperty ("GlobalC", "value4");
168                         engine.GlobalProperties.SetProperty ("GlobalD", "value5");
169                         Assert.AreEqual (4, engine.GlobalProperties.Count, "A13");
170                         Assert.AreEqual (3, project.GlobalProperties.Count, "A14");
171
172                         project = new Project (engine);
173                         Assert.AreEqual (4, project.GlobalProperties.Count, "A15");
174                 }
175
176                 [Test]
177                 public void TestGlobalEngine ()
178                 {
179                         engine = new Engine ();
180                         Assert.IsFalse (engine == Engine.GlobalEngine, "1");
181                         Assert.IsNotNull (Engine.GlobalEngine, "2");
182                         engine = Engine.GlobalEngine;
183                         Assert.AreSame (engine, Engine.GlobalEngine, "3");
184                 }
185
186                 [Test]
187                 [ExpectedException (typeof (ArgumentNullException))]
188                 [Category ("NotDotNet")]
189                 public void TestRegisterLogger ()
190                 {
191                         engine = new Engine (Consts.BinPath);
192                         engine.RegisterLogger (null);
193                 }
194
195                 // The "Project" object specified does not belong to the correct "Engine" object.
196                 [Test]
197                 [ExpectedException (typeof (InvalidOperationException))]
198                 public void TestUnloadProject1 ()
199                 {
200                         Engine a = new Engine (Consts.BinPath);
201                         Engine b = new Engine (Consts.BinPath);
202
203                         Project p = a.CreateNewProject ();
204
205                         b.UnloadProject (p);
206                 }
207
208                 [Test]
209                 [ExpectedException (typeof (ArgumentNullException))]
210                 [Category ("NotDotNet")]
211                 public void TestUnloadProject2 ()
212                 {
213                         Engine a = new Engine (Consts.BinPath);
214
215                         a.UnloadProject (null);
216                 }
217
218                 // This project object has been unloaded from the MSBuild engine and is no longer valid.
219                 [Test]
220                 [ExpectedException (typeof (InvalidOperationException))]
221                 public void TestUnloadProject3 ()
222                 {
223                         Engine a = new Engine (Consts.BinPath);
224                         Project p = a.CreateNewProject ();
225
226                         a.UnloadProject (p);
227                         a.UnloadProject (p);
228                 }
229
230                 [Test]
231                 [Category ("NotWorking")]
232                 public void TestUnregisterAllLoggers ()
233                 {
234                         engine = new Engine (Consts.BinPath);
235                         CheckUnregisterLogger cul = new CheckUnregisterLogger ();
236                         engine.RegisterLogger (cul);
237
238                         engine.UnregisterAllLoggers ();
239
240                         Assert.IsFalse (cul.Anything, "A1");
241                 }
242
243                 [Test]
244                 public void TestBuildError1 ()
245                 {
246                         engine = new Engine (Consts.BinPath);
247                         Project project = engine.CreateNewProject ();
248
249                         Assert.IsFalse (project.Build (), "A1");
250                         Assert.IsFalse (project.Build ((string)null), "A2");
251                         Assert.IsFalse (project.Build ((string [])null), "A3");
252                         Assert.IsFalse (project.Build (new string [0]), "A4");
253                         Assert.IsFalse (project.Build (null, null), "A5");
254                         Assert.IsFalse (project.Build (null, null, BuildSettings.None), "A6");
255                         //FIXME: Add test for Build (null, non-null-target)
256                 }
257
258                 [Test]
259                 public void TestBuildProjectFile1 ()
260                 {
261                         engine = new Engine (Consts.BinPath);
262                         Project project = engine.CreateNewProject ();
263                         project.LoadXml (@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
264                                         <Target Name='1'>
265                                                 <Message Text='Target 1 called'/>
266                                         </Target>
267                                 </Project>");
268
269                         Assert.IsTrue (project.Build ((string)null), "A1");
270                         Assert.IsTrue (project.Build ((string [])null), "A2");
271                         Assert.IsTrue (project.Build (new string [0]), "A3");
272                         Assert.IsTrue (project.Build (null, null), "A4");
273                         Assert.IsTrue (project.Build (null, null, BuildSettings.None), "A5");
274                         //FIXME: Add test for Build (null, non-null-target)
275                 }
276
277                 [Test]
278                 [ExpectedException (typeof (ArgumentException))]
279                 public void TestBuildProject1 ()
280                 {
281                         engine = new Engine (Consts.BinPath);
282                         engine.BuildProject (null);
283                 }
284
285                 [Test]
286                 public void TestBuildProject2 ()
287                 {
288                         engine = new Engine (Consts.BinPath);
289                         Project project = engine.CreateNewProject ();
290
291                         Assert.IsFalse (engine.BuildProject (project, (string)null), "#A1");
292                         Assert.IsFalse (engine.BuildProject (project, (string [])null), "#A2");
293                         Assert.IsFalse (engine.BuildProject (project, (string [])null, null), "#A3");
294                         Assert.IsFalse (engine.BuildProject (project, (string [])null, null, BuildSettings.None), "#A4");
295
296                         bool caught_exception = false;
297                         try {
298                                 //null string in targetNames [] param
299                                 engine.BuildProject (project, new string [] {null}, null);
300                         } catch {
301                                 caught_exception = true;
302                         }
303                         if (!caught_exception)
304                                 Assert.Fail ("Expected exception for Engine.BuildProject");
305                 }
306
307                 [Test]
308                 [ExpectedException (typeof (ArgumentException))]
309                 public void TestBuildProjectNull1 ()
310                 {
311                         engine = new Engine (Consts.BinPath);
312                         engine.BuildProject (null, "foo");
313                 }
314
315                 [Test]
316                 [ExpectedException (typeof (ArgumentException))]
317                 public void TestBuildProjectNull2 ()
318                 {
319                         engine = new Engine (Consts.BinPath);
320                         engine.BuildProject (null, (string)null);
321                 }
322
323                 // Tests to check global properties behavior
324                 [Test]
325                 public void TestGlobalProperties1 ()
326                 {
327                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
328                                 + GetUsingTask ("MSBuild")
329                                 + @"
330         <Target Name=""main"">
331                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
332                 <Message Text=""second""/>
333                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
334         </Target>
335 </Project>";
336
337                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
338                                 + GetUsingTask ("MSBuild")
339                                 + @"
340         <Target Name = ""1"">
341                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
342                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
343         </Target>
344         <Target Name=""2"">
345                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
346                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
347                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
348                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
349         </Target>
350 </Project>
351 ";
352
353                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
354                                 9, 7, 13,
355                                 new string [] {
356                                         "(TargetA) foo: bar A:  External: ",
357                                         "(TargetB) foo: foofoo A:  External: ",
358                                         "(TargetA) foo:  A:  External: ",
359                                         "(TargetB) foo: foofoo1 A:  External: ",
360                                         "second" });
361                 }
362
363                 [Test]
364                 public void TestGlobalProperties1a ()
365                 {
366                         Directory.CreateDirectory ("Test/resources/foo");
367                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
368                                         + GetUsingTask ("MSBuild")
369                                         + @"
370         <Target Name=""main"">
371                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
372                 <Message Text=""second""/>
373                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
374         </Target>
375 </Project>";
376
377                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
378                                         + GetUsingTask ("MSBuild")
379                                         + @"
380         <Target Name = ""1"">
381                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
382                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
383         </Target>
384         <Target Name=""2"">
385                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
386                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
387                 <MSBuild Projects=""second.proj"" Targets = ""TargetA"" Properties=""foo=bar""/>
388                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
389                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
390         </Target>
391 </Project>
392 ";
393                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
394                                 10, 7, 14,
395                                  new string [] {
396                                         "(TargetA) foo: bar A:  External: ",
397                                         "(TargetB) foo: foofoo A:  External: ",
398                                         "(TargetA) foo:  A:  External: ",
399                                         "(TargetB) foo: foofoo1 A:  External: ",
400                                         "second"});
401                 }
402
403                 [Test]
404                 public void TestGlobalProperties1b ()
405                 {
406                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
407                                         + GetUsingTask ("MSBuild")
408                                         + @"
409         <Target Name=""main"">
410                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
411                 <Message Text=""second""/>
412                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
413         </Target>
414 </Project>";
415
416                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
417                                         + GetUsingTask ("MSBuild")
418                                         + @"
419         <Target Name = ""1"">
420                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
421                 <MSBuild Projects=""second.proj""/>
422                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
423         </Target>
424         <Target Name=""2"">
425                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
426                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
427                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
428                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
429         </Target>
430 </Project>
431 ";
432                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
433                                 10, 7, 14,
434                                 new string [] {
435                                         "(TargetA) foo: bar A:  External: ",
436                                         "(TargetA) foo:  A:  External: ",
437                                         "(TargetB) foo: foofoo A:  External: ",
438                                         "(TargetB) foo: foofoo1 A:  External: ",
439                                         "second"});
440                 }
441
442                 [Test]
443                 public void TestGlobalProperties2 ()
444                 {
445                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
446                                         + GetUsingTask ("MSBuild")
447                                         + @"
448         <Target Name=""main"">
449                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
450                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
451                 <Message Text=""second""/>
452                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
453         </Target>
454 </Project>";
455
456                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
457                                         + GetUsingTask ("MSBuild")
458                                         + @"
459         <Target Name = ""1"">
460                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
461                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
462         </Target>
463         <Target Name=""2"">
464                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
465                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
466                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
467                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
468         </Target>
469 </Project>
470 ";
471
472                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
473                                 10, 7, 14,
474                                 new string [] {
475                                         "(TargetA) foo: bar A:  External: ",
476                                         "(TargetB) foo: foofoo A:  External: ",
477                                         "(TargetA) foo:  A:  External: ",
478                                         "(TargetB) foo: foofoo1 A:  External: ",
479                                         "second"});
480                 }
481
482                 [Test]
483                 public void TestGlobalProperties3 ()
484                 {
485                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
486                                         + GetUsingTask ("MSBuild")
487                                         + @"
488         <Target Name=""main"">
489                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
490                 <CallTarget Targets=""Call2""/>
491                 <Message Text=""second""/>
492                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
493         </Target>
494         <Target Name=""Call2"">
495                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
496         </Target>
497 </Project>";
498
499                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
500                                         + GetUsingTask ("MSBuild")
501                                         + @"
502         <Target Name = ""1"">
503                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
504                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
505         </Target>
506         <Target Name=""2"">
507                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
508                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
509                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
510                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
511         </Target>
512 </Project>
513 ";
514
515                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
516                                 10, 8, 15,
517                                 new string [] {
518                                         "(TargetA) foo: bar A:  External: ",
519                                         "(TargetB) foo: foofoo A:  External: ",
520                                         "(TargetA) foo:  A:  External: ",
521                                         "(TargetB) foo: foofoo1 A:  External: ",
522                                         "second"});
523                 }
524
525                 //externally set global properties
526                 [Test]
527                 public void TestGlobalProperties4 ()
528                 {
529                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
530                                         + GetUsingTask ("MSBuild")
531                                         + @"
532         <Target Name=""main"">
533                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
534                 <CallTarget Targets=""Call2""/>
535                 <Message Text=""second""/>
536                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
537         </Target>
538         <Target Name=""Call2"">
539                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
540         </Target>
541 </Project>";
542
543                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
544                                         + GetUsingTask ("MSBuild")
545                                         + @"
546         <Target Name = ""1"">
547                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
548                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
549         </Target>
550         <Target Name=""2"">
551                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
552                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
553                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
554                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
555         </Target>
556 </Project>
557 ";
558
559                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
560                         globalprops.SetProperty ("foo", "hello");
561                         engine.GlobalProperties = globalprops;
562
563                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
564                                 globalprops, null, 10, 8, 15,
565                                 new string [] {
566                                         "(TargetA) foo: bar A:  External: ",
567                                         "(TargetB) foo: foofoo A:  External: ",
568                                         "(TargetA) foo: hello A: FooWasHello External: ",
569                                         "(TargetB) foo: foofoo1 A:  External: ",
570                                         "second"});
571                 }
572
573                 //externally set global properties, merge with explicit
574                 [Test]
575                 public void TestGlobalProperties4a ()
576                 {
577                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
578                                         + GetUsingTask ("MSBuild")
579                                         + @"
580         <Target Name=""main"">
581                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
582                 <CallTarget Targets=""Call2""/>
583                 <Message Text=""second""/>
584                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
585         </Target>
586         <Target Name=""Call2"">
587                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
588         </Target>
589 </Project>";
590
591                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
592                                         + GetUsingTask ("MSBuild")
593                                         + @"
594         <Target Name = ""1"">
595                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
596                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
597         </Target>
598         <Target Name=""2"">
599                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
600                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
601                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
602                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
603         </Target>
604 </Project>
605 ";
606
607                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
608                         globalprops.SetProperty ("external", "ExternalValue");
609
610                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
611                                 globalprops, null,
612                                 10, 8, 15,
613                                 new string [] {
614                                         "(TargetA) foo: bar A:  External: ExternalValue",
615                                         "(TargetB) foo: foofoo A:  External: ExternalValue",
616                                         "(TargetA) foo:  A:  External: ExternalValue",
617                                         "(TargetB) foo: foofoo1 A:  External: ExternalValue",
618                                         "second"});
619                 }
620
621                 //set global properties on _project_, merge with explicit
622                 [Test]
623                 public void TestGlobalProperties4b ()
624                 {
625                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
626                                         + GetUsingTask ("MSBuild")
627                                         + @"
628         <Target Name=""main"">
629                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
630                 <CallTarget Targets=""Call2""/>
631                 <Message Text=""second""/>
632                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
633         </Target>
634         <Target Name=""Call2"">
635                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
636         </Target>
637 </Project>";
638
639                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
640                                         + GetUsingTask ("MSBuild")
641                                         + @"
642         <Target Name = ""1"">
643                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
644                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
645         </Target>
646         <Target Name=""2"">
647                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
648                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
649                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
650                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
651         </Target>
652 </Project>
653 ";
654
655                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
656                         globalprops.SetProperty ("external", "ExternalValue");
657
658                         BuildPropertyGroup project_globalprops = new BuildPropertyGroup ();
659                         project_globalprops.SetProperty ("external", "ProjExternalValue");
660                         project_globalprops.SetProperty ("foo", "ProjFooValue");
661
662                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
663                                 globalprops, project_globalprops,
664                                 10, 8, 15,
665                                 new string [] {
666                                         "(TargetA) foo: bar A:  External: ProjExternalValue",
667                                         "(TargetB) foo: foofoo A:  External: ProjExternalValue",
668                                         "(TargetA) foo: ProjFooValue A:  External: ProjExternalValue",
669                                         "(TargetB) foo: foofoo1 A:  External: ProjExternalValue",
670                                         "second"});
671                 }
672
673                 //set global properties on _project_, and engine and explicit via msbuild
674                 [Test]
675                 public void TestGlobalProperties4c ()
676                 {
677                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
678                                         + GetUsingTask ("MSBuild")
679                                         + @"
680         <Target Name=""main"">
681                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
682                 <CallTarget Targets=""Call2""/>
683                 <Message Text=""second""/>
684                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
685         </Target>
686         <Target Name=""Call2"">
687                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
688         </Target>
689 </Project>";
690
691                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
692                                         + GetUsingTask ("MSBuild")
693                                         + @"
694         <Target Name = ""1"">
695                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
696                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
697         </Target>
698         <Target Name=""2"">
699                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
700                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
701                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
702                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
703         </Target>
704 </Project>
705 ";
706
707                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
708                         globalprops.SetProperty ("foo", "EngineFooValue");
709
710                         BuildPropertyGroup project_globalprops = new BuildPropertyGroup ();
711                         project_globalprops.SetProperty ("foo", "ProjFooValue");
712
713                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
714                                 globalprops, project_globalprops,
715                                 10, 8, 15,
716                                 new string [] {
717                                         "(TargetA) foo: bar A:  External: ",
718                                         "(TargetB) foo: foofoo A:  External: ",
719                                         "(TargetA) foo: ProjFooValue A:  External: ",
720                                         "(TargetB) foo: foofoo1 A:  External: ",
721                                         "second"});
722                 }
723                 [Test]
724                 public void TestMSBuildOutputs ()
725                 {
726                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
727                                         + GetUsingTask ("MSBuild")
728                                         + @"
729         <ItemGroup>
730                 <ProjectRef Include=""first.proj"">
731                         <Prop3>value</Prop3>
732                         <Unique>true</Unique>
733                 </ProjectRef>
734                 <ProjectRef Include=""first.proj"">
735                         <Prop3>value2</Prop3>
736                         <Unique>false</Unique>
737                 </ProjectRef>
738                 
739                 <ProjectRef Include=""second.proj"">
740                         <Prop3>value3</Prop3>
741                         <Unique>unique</Unique>
742                 </ProjectRef>
743
744         </ItemGroup>
745
746         <Target Name='Main'>
747                 <MSBuild Projects=""@(ProjectRef)"" Targets=""GetData"">
748                         <Output TaskParameter=""TargetOutputs"" ItemName=""F""/>
749                 </MSBuild>
750                 <Message Text=""@(F): F.Unique: %(F.Unique)""/>
751                 <Message Text=""@(F): F.Prop1: %(F.Prop1)""/>
752                 <Message Text=""@(F): F.Prop2: %(F.Prop2)""/>
753                 <Message Text=""@(F): F.Prop3: %(F.Prop3)""/>
754         </Target>
755 </Project>";
756
757                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
758         <ItemGroup>
759                 <A Include=""foofoo"">
760                         <Prop1>false</Prop1>
761                         <Prop2>false</Prop2>
762                         <Prop3>foo value</Prop3>
763                 </A>
764                 
765                 <A Include=""barbar"">
766                         <Prop1>bar_false</Prop1>
767                         <Prop2>bar_false</Prop2>
768                         <Prop3>bar value</Prop3>
769                 </A>
770
771         </ItemGroup>
772
773         <Target Name=""GetData"" Outputs=""@(AbcOutputs)"">
774                 <CreateItem Include=""@(A)"">
775                         <Output TaskParameter=""Include"" ItemName=""AbcOutputs""/>
776                 </CreateItem>
777         </Target>
778 </Project>
779 ";
780                         string secondProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
781         <ItemGroup>
782                 <A Include=""from_second"">
783                         <Prop1>false</Prop1>
784                         <Prop2>false</Prop2>
785                         <Prop3>new value</Prop3>
786                 </A>
787         </ItemGroup>
788
789         <Target Name=""GetData"" Outputs=""@(AbcOutputs)"">
790                 <CreateItem Include=""@(A)"">
791                         <Output TaskParameter=""Include"" ItemName=""AbcOutputs""/>
792                 </CreateItem>
793         </Target>
794 </Project>
795 ";
796
797                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
798                                 null, null,
799                                 4, 3, 12,
800                                 new string [] {
801                                         "foofoo;barbar;foofoo;barbar: F.Unique: true",
802                                         "from_second: F.Unique: unique",
803                                         "foofoo;foofoo;from_second: F.Prop1: false",
804                                         "barbar;barbar: F.Prop1: bar_false",
805                                         "foofoo;foofoo;from_second: F.Prop2: false",
806                                         "barbar;barbar: F.Prop2: bar_false",
807                                         "foofoo;foofoo: F.Prop3: foo value",
808                                         "barbar;barbar: F.Prop3: bar value",
809                                         "from_second: F.Prop3: new value",
810                                 });
811                 }
812
813                 // Helper Methods for TestGlobalProperties*
814
815                 void CreateAndCheckGlobalPropertiesTest (string main, string first, string second,
816                         int project_count, int target_count, int task_count, string [] messages)
817                 {
818                         CreateAndCheckGlobalPropertiesTest (main, first, second, null, null,
819                                 project_count, target_count, task_count, messages);
820                 }
821
822                 void CreateAndCheckGlobalPropertiesTest (string main, string first, string second,
823                         BuildPropertyGroup engine_globals, BuildPropertyGroup project_globals,
824                         int project_count, int target_count, int task_count, string [] messages)
825                 {
826                         WriteGlobalPropertiesProjects (main, first, second);
827
828                         Engine engine = new Engine (Consts.BinPath);
829                         if (engine_globals != null)
830                                 engine.GlobalProperties = engine_globals;
831                         MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
832                                 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
833                         engine.RegisterLogger (logger);
834
835                         Project project = engine.CreateNewProject ();
836                         project.Load (Path.Combine ("Test", Path.Combine ("resources", "main.proj")));
837                         if (project_globals != null)
838                                 project.GlobalProperties = project_globals;
839
840                         bool result = project.Build ();
841                         if (!result) {
842                                 logger.DumpMessages ();
843                                 Assert.Fail ("Build failed");
844                         }
845
846                         CheckEventCounts (logger, project_count, target_count, task_count);
847
848                         CheckLoggedMessages (logger, messages, "A1");
849                 }
850
851                 void CheckEventCounts (MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger,
852                         int project, int target, int task)
853                 {
854                         try {
855                                 Assert.AreEqual (project, logger.ProjectStarted, "#project started events");
856                                 Assert.AreEqual (project, logger.ProjectFinished, "#project finished events");
857                                 Assert.AreEqual (target, logger.TargetStarted, "#target started events");
858                                 Assert.AreEqual (target, logger.TargetFinished, "#target finished events");
859                                 Assert.AreEqual (task, logger.TaskStarted, "#task started events");
860                                 Assert.AreEqual (task, logger.TaskFinished, "#task finished events");
861                                 Assert.AreEqual (1, logger.BuildStarted, "#build started events");
862                                 Assert.AreEqual (1, logger.BuildFinished, "#build finished events");
863                         } catch (AssertionException) {
864                                 logger.DumpMessages ();
865                                 throw;
866                         }
867                 }
868
869                 void CheckLoggedMessages (MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger, string [] messages,
870                         string prefix)
871                 {
872                         try {
873                                 for (int i = 0; i < messages.Length; i++) {
874                                         logger.CheckLoggedMessageHead (messages [i], String.Format ("{0} #{1}", prefix, i));
875                                 }
876                         } catch {
877                                 logger.DumpMessages ();
878                                 throw;
879                         }
880
881                         Assert.AreEqual (0, logger.NormalMessageCount, "Number of remaining messages");
882                 }
883
884                 // helper methods for TestGlobalProperties*
885                 void WriteGlobalPropertiesProjects (string mainProject, string firstProject, string secondProject)
886                 {
887                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "main.proj")))) {
888                                 sw.Write (mainProject);
889                         }
890
891                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "first.proj")))) {
892                                 sw.Write (firstProject);
893                         }
894
895                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "second.proj")))) {
896                                 sw.Write (secondProject);
897                         }
898                 }
899
900                 public static string GetUsingTask (string taskName)
901                 {
902                         return "<UsingTask TaskName='Microsoft.Build.Tasks." + taskName + "' AssemblyFile='" + Consts.GetTasksAsmPath () + "' />";
903                 }
904         }
905 }