[xbuild]: Support <PropertyGroup/ItemGroup> inside <Target>.
[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                 [Category ("NotDotNet")]
279                 [ExpectedException (typeof (ArgumentException))]
280                 public void TestBuildProject1 ()
281                 {
282                         engine = new Engine (Consts.BinPath);
283                         engine.BuildProject (null);
284                 }
285
286                 [Test]
287                 public void TestBuildProject2 ()
288                 {
289                         engine = new Engine (Consts.BinPath);
290                         Project project = engine.CreateNewProject ();
291
292                         Assert.IsFalse (engine.BuildProject (project, (string)null), "#A1");
293                         Assert.IsFalse (engine.BuildProject (project, (string [])null), "#A2");
294                         Assert.IsFalse (engine.BuildProject (project, (string [])null, null), "#A3");
295                         Assert.IsFalse (engine.BuildProject (project, (string [])null, null, BuildSettings.None), "#A4");
296
297                         bool caught_exception = false;
298                         try {
299                                 //null string in targetNames [] param
300                                 engine.BuildProject (project, new string [] {null}, null);
301                         } catch {
302                                 caught_exception = true;
303                         }
304                         if (!caught_exception)
305                                 Assert.Fail ("Expected exception for Engine.BuildProject");
306                 }
307
308                 [Test]
309                 [Category ("NotDotNet")]
310                 [ExpectedException (typeof (ArgumentException))]
311                 public void TestBuildProjectNull1 ()
312                 {
313                         engine = new Engine (Consts.BinPath);
314                         engine.BuildProject (null, "foo");
315                 }
316
317                 [Test]
318                 [Category ("NotDotNet")]
319                 [ExpectedException (typeof (ArgumentException))]
320                 public void TestBuildProjectNull2 ()
321                 {
322                         engine = new Engine (Consts.BinPath);
323                         engine.BuildProject (null, (string)null);
324                 }
325
326                 // Tests to check global properties behavior
327                 [Test]
328                 public void TestGlobalProperties1 ()
329                 {
330                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
331                                 + GetUsingTask ("MSBuild")
332                                 + @"
333         <Target Name=""main"">
334                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
335                 <Message Text=""second""/>
336                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
337         </Target>
338 </Project>";
339
340                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
341                                 + GetUsingTask ("MSBuild")
342                                 + @"
343         <Target Name = ""1"">
344                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
345                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
346         </Target>
347         <Target Name=""2"">
348                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
349                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
350                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
351                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
352         </Target>
353 </Project>
354 ";
355
356                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
357                                 9, 7, 13,
358                                 new string [] {
359                                         "(TargetA) foo: bar A:  External: ",
360                                         "(TargetB) foo: foofoo A:  External: ",
361                                         "(TargetA) foo:  A:  External: ",
362                                         "(TargetB) foo: foofoo1 A:  External: ",
363                                         "second" });
364                 }
365
366                 [Test]
367                 public void TestGlobalProperties1a ()
368                 {
369                         Directory.CreateDirectory ("Test/resources/foo");
370                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
371                                         + GetUsingTask ("MSBuild")
372                                         + @"
373         <Target Name=""main"">
374                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
375                 <Message Text=""second""/>
376                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
377         </Target>
378 </Project>";
379
380                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
381                                         + GetUsingTask ("MSBuild")
382                                         + @"
383         <Target Name = ""1"">
384                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
385                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
386         </Target>
387         <Target Name=""2"">
388                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
389                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
390                 <MSBuild Projects=""second.proj"" Targets = ""TargetA"" Properties=""foo=bar""/>
391                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
392                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
393         </Target>
394 </Project>
395 ";
396                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
397                                 10, 7, 14,
398                                  new string [] {
399                                         "(TargetA) foo: bar A:  External: ",
400                                         "(TargetB) foo: foofoo A:  External: ",
401                                         "(TargetA) foo:  A:  External: ",
402                                         "(TargetB) foo: foofoo1 A:  External: ",
403                                         "second"});
404                 }
405
406                 [Test]
407                 public void TestGlobalProperties1b ()
408                 {
409                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
410                                         + GetUsingTask ("MSBuild")
411                                         + @"
412         <Target Name=""main"">
413                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
414                 <Message Text=""second""/>
415                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
416         </Target>
417 </Project>";
418
419                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
420                                         + GetUsingTask ("MSBuild")
421                                         + @"
422         <Target Name = ""1"">
423                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
424                 <MSBuild Projects=""second.proj""/>
425                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
426         </Target>
427         <Target Name=""2"">
428                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
429                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
430                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
431                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
432         </Target>
433 </Project>
434 ";
435                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
436                                 10, 7, 14,
437                                 new string [] {
438                                         "(TargetA) foo: bar A:  External: ",
439                                         "(TargetA) foo:  A:  External: ",
440                                         "(TargetB) foo: foofoo A:  External: ",
441                                         "(TargetB) foo: foofoo1 A:  External: ",
442                                         "second"});
443                 }
444
445                 [Test]
446                 public void TestGlobalProperties2 ()
447                 {
448                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
449                                         + GetUsingTask ("MSBuild")
450                                         + @"
451         <Target Name=""main"">
452                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
453                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
454                 <Message Text=""second""/>
455                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
456         </Target>
457 </Project>";
458
459                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
460                                         + GetUsingTask ("MSBuild")
461                                         + @"
462         <Target Name = ""1"">
463                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
464                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
465         </Target>
466         <Target Name=""2"">
467                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
468                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
469                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
470                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
471         </Target>
472 </Project>
473 ";
474
475                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
476                                 10, 7, 14,
477                                 new string [] {
478                                         "(TargetA) foo: bar A:  External: ",
479                                         "(TargetB) foo: foofoo A:  External: ",
480                                         "(TargetA) foo:  A:  External: ",
481                                         "(TargetB) foo: foofoo1 A:  External: ",
482                                         "second"});
483                 }
484
485                 [Test]
486                 public void TestGlobalProperties3 ()
487                 {
488                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
489                                         + GetUsingTask ("MSBuild")
490                                         + @"
491         <Target Name=""main"">
492                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
493                 <CallTarget Targets=""Call2""/>
494                 <Message Text=""second""/>
495                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
496         </Target>
497         <Target Name=""Call2"">
498                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
499         </Target>
500 </Project>";
501
502                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
503                                         + GetUsingTask ("MSBuild")
504                                         + @"
505         <Target Name = ""1"">
506                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
507                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
508         </Target>
509         <Target Name=""2"">
510                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
511                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
512                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
513                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
514         </Target>
515 </Project>
516 ";
517
518                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
519                                 10, 8, 15,
520                                 new string [] {
521                                         "(TargetA) foo: bar A:  External: ",
522                                         "(TargetB) foo: foofoo A:  External: ",
523                                         "(TargetA) foo:  A:  External: ",
524                                         "(TargetB) foo: foofoo1 A:  External: ",
525                                         "second"});
526                 }
527
528                 //externally set global properties
529                 [Test]
530                 public void TestGlobalProperties4 ()
531                 {
532                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
533                                         + GetUsingTask ("MSBuild")
534                                         + @"
535         <Target Name=""main"">
536                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
537                 <CallTarget Targets=""Call2""/>
538                 <Message Text=""second""/>
539                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
540         </Target>
541         <Target Name=""Call2"">
542                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
543         </Target>
544 </Project>";
545
546                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
547                                         + GetUsingTask ("MSBuild")
548                                         + @"
549         <Target Name = ""1"">
550                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
551                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
552         </Target>
553         <Target Name=""2"">
554                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
555                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
556                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
557                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
558         </Target>
559 </Project>
560 ";
561
562                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
563                         globalprops.SetProperty ("foo", "hello");
564                         engine.GlobalProperties = globalprops;
565
566                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
567                                 globalprops, null, 10, 8, 15,
568                                 new string [] {
569                                         "(TargetA) foo: bar A:  External: ",
570                                         "(TargetB) foo: foofoo A:  External: ",
571                                         "(TargetA) foo: hello A: FooWasHello External: ",
572                                         "(TargetB) foo: foofoo1 A:  External: ",
573                                         "second"});
574                 }
575
576                 //externally set global properties, merge with explicit
577                 [Test]
578                 public void TestGlobalProperties4a ()
579                 {
580                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
581                                         + GetUsingTask ("MSBuild")
582                                         + @"
583         <Target Name=""main"">
584                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
585                 <CallTarget Targets=""Call2""/>
586                 <Message Text=""second""/>
587                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
588         </Target>
589         <Target Name=""Call2"">
590                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
591         </Target>
592 </Project>";
593
594                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
595                                         + GetUsingTask ("MSBuild")
596                                         + @"
597         <Target Name = ""1"">
598                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
599                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
600         </Target>
601         <Target Name=""2"">
602                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
603                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
604                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
605                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
606         </Target>
607 </Project>
608 ";
609
610                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
611                         globalprops.SetProperty ("external", "ExternalValue");
612
613                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
614                                 globalprops, null,
615                                 10, 8, 15,
616                                 new string [] {
617                                         "(TargetA) foo: bar A:  External: ExternalValue",
618                                         "(TargetB) foo: foofoo A:  External: ExternalValue",
619                                         "(TargetA) foo:  A:  External: ExternalValue",
620                                         "(TargetB) foo: foofoo1 A:  External: ExternalValue",
621                                         "second"});
622                 }
623
624                 //set global properties on _project_, merge with explicit
625                 [Test]
626                 public void TestGlobalProperties4b ()
627                 {
628                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
629                                         + GetUsingTask ("MSBuild")
630                                         + @"
631         <Target Name=""main"">
632                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
633                 <CallTarget Targets=""Call2""/>
634                 <Message Text=""second""/>
635                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
636         </Target>
637         <Target Name=""Call2"">
638                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
639         </Target>
640 </Project>";
641
642                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
643                                         + GetUsingTask ("MSBuild")
644                                         + @"
645         <Target Name = ""1"">
646                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
647                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
648         </Target>
649         <Target Name=""2"">
650                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
651                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
652                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
653                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
654         </Target>
655 </Project>
656 ";
657
658                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
659                         globalprops.SetProperty ("external", "ExternalValue");
660
661                         BuildPropertyGroup project_globalprops = new BuildPropertyGroup ();
662                         project_globalprops.SetProperty ("external", "ProjExternalValue");
663                         project_globalprops.SetProperty ("foo", "ProjFooValue");
664
665                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
666                                 globalprops, project_globalprops,
667                                 10, 8, 15,
668                                 new string [] {
669                                         "(TargetA) foo: bar A:  External: ProjExternalValue",
670                                         "(TargetB) foo: foofoo A:  External: ProjExternalValue",
671                                         "(TargetA) foo: ProjFooValue A:  External: ProjExternalValue",
672                                         "(TargetB) foo: foofoo1 A:  External: ProjExternalValue",
673                                         "second"});
674                 }
675
676                 //set global properties on _project_, and engine and explicit via msbuild
677                 [Test]
678                 public void TestGlobalProperties4c ()
679                 {
680                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
681                                         + GetUsingTask ("MSBuild")
682                                         + @"
683         <Target Name=""main"">
684                 <MSBuild Projects=""first.proj"" Targets = ""1""/>
685                 <CallTarget Targets=""Call2""/>
686                 <Message Text=""second""/>
687                 <MSBuild Projects=""first.proj"" Targets = ""1;2""/>
688         </Target>
689         <Target Name=""Call2"">
690                 <MSBuild Projects=""first.proj"" Targets = ""2""/>
691         </Target>
692 </Project>";
693
694                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
695                                         + GetUsingTask ("MSBuild")
696                                         + @"
697         <Target Name = ""1"">
698                 <MSBuild Projects=""second.proj"" Properties=""foo=bar""/>
699                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo""/>
700         </Target>
701         <Target Name=""2"">
702                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
703                 <MSBuild Projects=""second.proj"" Targets = ""TargetA""/>
704                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo"" />
705                 <MSBuild Projects=""second.proj"" Targets = ""TargetB"" Properties=""foo=foofoo1"" />
706         </Target>
707 </Project>
708 ";
709
710                         BuildPropertyGroup globalprops = new BuildPropertyGroup ();
711                         globalprops.SetProperty ("foo", "EngineFooValue");
712
713                         BuildPropertyGroup project_globalprops = new BuildPropertyGroup ();
714                         project_globalprops.SetProperty ("foo", "ProjFooValue");
715
716                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
717                                 globalprops, project_globalprops,
718                                 10, 8, 15,
719                                 new string [] {
720                                         "(TargetA) foo: bar A:  External: ",
721                                         "(TargetB) foo: foofoo A:  External: ",
722                                         "(TargetA) foo: ProjFooValue A:  External: ",
723                                         "(TargetB) foo: foofoo1 A:  External: ",
724                                         "second"});
725                 }
726
727                 // Check for global properties in case of Import
728
729                 [Test]
730                 public void TestGlobalPropertiesImport1 ()
731                 {
732                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
733                                 <Target Name=""main"">
734                                         <MSBuild Projects=""first.proj"" Targets = ""1"" Properties='Prop=test'/>
735                                 </Target>
736                         </Project>";
737
738                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
739                                 <Target Name = ""1"">
740                                         <Message Text='Prop: $(Prop)'/>
741                                 </Target>
742                                 <Import Project='$(Prop).proj'/>
743                         </Project>";
744
745                         CreateAndCheckGlobalPropertiesImportTest (mainProject, firstProject);
746                 }
747
748                 [Test]
749                 public void TestGlobalPropertiesImport2 ()
750                 {
751                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
752                                 <Target Name=""main"">
753                                         <MSBuild Projects=""first.proj"" Targets = ""1"" Properties='Prop=test'/>
754                                 </Target>
755                         </Project>";
756
757                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
758                                 <PropertyGroup>
759                                         <Prop>invalid</Prop>
760                                 </PropertyGroup>
761                                 <Target Name = ""1"">
762                                         <Message Text='Prop: $(Prop)'/>
763                                 </Target>
764                                 <Import Project='$(Prop).proj'/>
765                         </Project>";
766
767                         CreateAndCheckGlobalPropertiesImportTest (mainProject, firstProject);
768                 }
769
770                 [Test]
771                 public void TestGlobalPropertiesImport3()
772                 {
773                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
774                                 <Target Name=""main"">
775                                         <MSBuild Projects=""first.proj"" Targets = ""1""/>
776                                 </Target>
777                         </Project>";
778
779                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
780                                 <PropertyGroup>
781                                         <Prop>test</Prop>
782                                 </PropertyGroup>
783                                 <Target Name = ""1"">
784                                         <Message Text='Prop: $(Prop)'/>
785                                 </Target>
786                                 <Import Project='$(Prop).proj'/>
787                         </Project>";
788
789                         CreateAndCheckGlobalPropertiesImportTest (mainProject, firstProject);
790                 }
791
792                 [Test]
793                 public void TestMSBuildOutputs ()
794                 {
795                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
796                                         + GetUsingTask ("MSBuild")
797                                         + @"
798         <ItemGroup>
799                 <ProjectRef Include=""first.proj"">
800                         <Prop3>value</Prop3>
801                         <Unique>true</Unique>
802                 </ProjectRef>
803                 <ProjectRef Include=""first.proj"">
804                         <Prop3>value2</Prop3>
805                         <Unique>false</Unique>
806                 </ProjectRef>
807                 
808                 <ProjectRef Include=""second.proj"">
809                         <Prop3>value3</Prop3>
810                         <Unique>unique</Unique>
811                 </ProjectRef>
812
813         </ItemGroup>
814
815         <Target Name='Main'>
816                 <MSBuild Projects=""@(ProjectRef)"" Targets=""GetData"">
817                         <Output TaskParameter=""TargetOutputs"" ItemName=""F""/>
818                 </MSBuild>
819                 <Message Text=""@(F): F.Unique: %(F.Unique)""/>
820                 <Message Text=""@(F): F.Prop1: %(F.Prop1)""/>
821                 <Message Text=""@(F): F.Prop2: %(F.Prop2)""/>
822                 <Message Text=""@(F): F.Prop3: %(F.Prop3)""/>
823         </Target>
824 </Project>";
825
826                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
827         <ItemGroup>
828                 <A Include=""foofoo"">
829                         <Prop1>false</Prop1>
830                         <Prop2>false</Prop2>
831                         <Prop3>foo value</Prop3>
832                 </A>
833                 
834                 <A Include=""barbar"">
835                         <Prop1>bar_false</Prop1>
836                         <Prop2>bar_false</Prop2>
837                         <Prop3>bar value</Prop3>
838                 </A>
839
840         </ItemGroup>
841
842         <Target Name=""GetData"" Outputs=""@(AbcOutputs)"">
843                 <CreateItem Include=""@(A)"">
844                         <Output TaskParameter=""Include"" ItemName=""AbcOutputs""/>
845                 </CreateItem>
846         </Target>
847 </Project>
848 ";
849                         string secondProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
850         <ItemGroup>
851                 <A Include=""from_second"">
852                         <Prop1>false</Prop1>
853                         <Prop2>false</Prop2>
854                         <Prop3>new value</Prop3>
855                 </A>
856         </ItemGroup>
857
858         <Target Name=""GetData"" Outputs=""@(AbcOutputs)"">
859                 <CreateItem Include=""@(A)"">
860                         <Output TaskParameter=""Include"" ItemName=""AbcOutputs""/>
861                 </CreateItem>
862         </Target>
863 </Project>
864 ";
865
866                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
867                                 null, null,
868                                 4, 3, 13,
869                                 new string [] {
870                                         "foofoo;barbar: F.Unique: true",
871                                         "foofoo;barbar: F.Unique: false",
872                                         "from_second: F.Unique: unique",
873                                         "foofoo;foofoo;from_second: F.Prop1: false",
874                                         "barbar;barbar: F.Prop1: bar_false",
875                                         "foofoo;foofoo;from_second: F.Prop2: false",
876                                         "barbar;barbar: F.Prop2: bar_false",
877                                         "foofoo;foofoo: F.Prop3: foo value",
878                                         "barbar;barbar: F.Prop3: bar value",
879                                         "from_second: F.Prop3: new value",
880                                 });
881                 }
882
883                 [Test]
884                 public void TestGetLoadedProject1()
885                 {
886                         Project project = Engine.GlobalEngine.GetLoadedProject("foo.proj");
887                         Assert.IsNull(project);
888                 }
889
890                 void CreateAndCheckGlobalPropertiesImportTest (string main, string first)
891                 {
892                         string basePath = Path.Combine ("Test", "resources");
893
894                         string testProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
895 </Project>";
896
897                         File.WriteAllText (Path.Combine (basePath, "main.proj"), main);
898                         File.WriteAllText (Path.Combine (basePath, "first.proj"), first);
899                         File.WriteAllText (Path.Combine (basePath, "test.proj"), testProject);
900
901                         try {
902                                 Engine engine = new Engine ();
903                                 MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
904                                         new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
905                                 engine.RegisterLogger (logger);
906
907                                 Project project = engine.CreateNewProject ();
908                                 project.Load (Path.Combine (basePath, "main.proj"));
909
910                                 bool result = project.Build ();
911                                 if (!result) {
912                                         logger.DumpMessages ();
913                                         Assert.Fail ("Build failed");
914                                 }
915
916                                 logger.CheckAny ("Prop: test", MessageImportance.Normal);
917                                 Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
918                         } finally {
919                                 File.Delete (Path.Combine (basePath, "main.proj"));
920                                 File.Delete (Path.Combine (basePath, "first.proj"));
921                                 File.Delete (Path.Combine (basePath, "test.proj"));
922                         }
923                 }
924
925                 // Helper Methods for TestGlobalProperties*
926
927                 void CreateAndCheckGlobalPropertiesTest (string main, string first, string second,
928                         int project_count, int target_count, int task_count, string [] messages)
929                 {
930                         CreateAndCheckGlobalPropertiesTest (main, first, second, null, null,
931                                 project_count, target_count, task_count, messages);
932                 }
933
934                 void CreateAndCheckGlobalPropertiesTest (string main, string first, string second,
935                         BuildPropertyGroup engine_globals, BuildPropertyGroup project_globals,
936                         int project_count, int target_count, int task_count, string [] messages)
937                 {
938                         WriteGlobalPropertiesProjects (main, first, second);
939
940                         Engine engine = new Engine (Consts.BinPath);
941                         if (engine_globals != null)
942                                 engine.GlobalProperties = engine_globals;
943                         MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
944                                 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
945                         engine.RegisterLogger (logger);
946
947                         Project project = engine.CreateNewProject ();
948                         project.Load (Path.Combine ("Test", Path.Combine ("resources", "main.proj")));
949                         if (project_globals != null)
950                                 project.GlobalProperties = project_globals;
951
952                         bool result = project.Build ();
953                         if (!result) {
954                                 logger.DumpMessages ();
955                                 Assert.Fail ("Build failed");
956                         }
957
958                         CheckEventCounts (logger, project_count, target_count, task_count);
959
960                         CheckLoggedMessages (logger, messages, "A1");
961                 }
962
963                 void CheckEventCounts (MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger,
964                         int project, int target, int task)
965                 {
966                         try {
967                                 Assert.AreEqual (project, logger.ProjectStarted, "#project started events");
968                                 Assert.AreEqual (project, logger.ProjectFinished, "#project finished events");
969                                 Assert.AreEqual (target, logger.TargetStarted, "#target started events");
970                                 Assert.AreEqual (target, logger.TargetFinished, "#target finished events");
971                                 Assert.AreEqual (task, logger.TaskStarted, "#task started events");
972                                 Assert.AreEqual (task, logger.TaskFinished, "#task finished events");
973                                 Assert.AreEqual (1, logger.BuildStarted, "#build started events");
974                                 Assert.AreEqual (1, logger.BuildFinished, "#build finished events");
975                         } catch (AssertionException) {
976                                 logger.DumpMessages ();
977                                 throw;
978                         }
979                 }
980
981                 void CheckLoggedMessages (MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger, string [] messages,
982                         string prefix)
983                 {
984                         try {
985                                 for (int i = 0; i < messages.Length; i++) {
986                                         logger.CheckLoggedMessageHead (messages [i], String.Format ("{0} #{1}", prefix, i));
987                                 }
988                         } catch {
989                                 logger.DumpMessages ();
990                                 throw;
991                         }
992
993                         Assert.AreEqual (0, logger.NormalMessageCount, "Number of remaining messages");
994                 }
995
996                 // helper methods for TestGlobalProperties*
997                 void WriteGlobalPropertiesProjects (string mainProject, string firstProject, string secondProject)
998                 {
999                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "main.proj")))) {
1000                                 sw.Write (mainProject);
1001                         }
1002
1003                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "first.proj")))) {
1004                                 sw.Write (firstProject);
1005                         }
1006
1007                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "second.proj")))) {
1008                                 sw.Write (secondProject);
1009                         }
1010                 }
1011
1012                 public static string GetUsingTask (string taskName)
1013                 {
1014                         return "<UsingTask TaskName='Microsoft.Build.Tasks." + taskName + "' AssemblyFile='" + Consts.GetTasksAsmPath () + "' />";
1015                 }
1016         }
1017 }