[xbuild] Copy metadata from Project items to target outputs.
[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
724                 // Check for global properties in case of Import
725
726                 [Test]
727                 public void TestGlobalPropertiesImport1 ()
728                 {
729                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
730                                 <Target Name=""main"">
731                                         <MSBuild Projects=""first.proj"" Targets = ""1"" Properties='Prop=test'/>
732                                 </Target>
733                         </Project>";
734
735                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
736                                 <Target Name = ""1"">
737                                         <Message Text='Prop: $(Prop)'/>
738                                 </Target>
739                                 <Import Project='$(Prop).proj'/>
740                         </Project>";
741
742                         CreateAndCheckGlobalPropertiesImportTest (mainProject, firstProject);
743                 }
744
745                 [Test]
746                 public void TestGlobalPropertiesImport2 ()
747                 {
748                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
749                                 <Target Name=""main"">
750                                         <MSBuild Projects=""first.proj"" Targets = ""1"" Properties='Prop=test'/>
751                                 </Target>
752                         </Project>";
753
754                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
755                                 <PropertyGroup>
756                                         <Prop>invalid</Prop>
757                                 </PropertyGroup>
758                                 <Target Name = ""1"">
759                                         <Message Text='Prop: $(Prop)'/>
760                                 </Target>
761                                 <Import Project='$(Prop).proj'/>
762                         </Project>";
763
764                         CreateAndCheckGlobalPropertiesImportTest (mainProject, firstProject);
765                 }
766
767                 [Test]
768                 public void TestGlobalPropertiesImport3()
769                 {
770                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
771                                 <Target Name=""main"">
772                                         <MSBuild Projects=""first.proj"" Targets = ""1""/>
773                                 </Target>
774                         </Project>";
775
776                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
777                                 <PropertyGroup>
778                                         <Prop>test</Prop>
779                                 </PropertyGroup>
780                                 <Target Name = ""1"">
781                                         <Message Text='Prop: $(Prop)'/>
782                                 </Target>
783                                 <Import Project='$(Prop).proj'/>
784                         </Project>";
785
786                         CreateAndCheckGlobalPropertiesImportTest (mainProject, firstProject);
787                 }
788
789                 [Test]
790                 public void TestMSBuildOutputs ()
791                 {
792                         string mainProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">"
793                                         + GetUsingTask ("MSBuild")
794                                         + @"
795         <ItemGroup>
796                 <ProjectRef Include=""first.proj"">
797                         <Prop3>value</Prop3>
798                         <Unique>true</Unique>
799                 </ProjectRef>
800                 <ProjectRef Include=""first.proj"">
801                         <Prop3>value2</Prop3>
802                         <Unique>false</Unique>
803                 </ProjectRef>
804                 
805                 <ProjectRef Include=""second.proj"">
806                         <Prop3>value3</Prop3>
807                         <Unique>unique</Unique>
808                 </ProjectRef>
809
810         </ItemGroup>
811
812         <Target Name='Main'>
813                 <MSBuild Projects=""@(ProjectRef)"" Targets=""GetData"">
814                         <Output TaskParameter=""TargetOutputs"" ItemName=""F""/>
815                 </MSBuild>
816                 <Message Text=""@(F): F.Unique: %(F.Unique)""/>
817                 <Message Text=""@(F): F.Prop1: %(F.Prop1)""/>
818                 <Message Text=""@(F): F.Prop2: %(F.Prop2)""/>
819                 <Message Text=""@(F): F.Prop3: %(F.Prop3)""/>
820         </Target>
821 </Project>";
822
823                         string firstProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
824         <ItemGroup>
825                 <A Include=""foofoo"">
826                         <Prop1>false</Prop1>
827                         <Prop2>false</Prop2>
828                         <Prop3>foo value</Prop3>
829                 </A>
830                 
831                 <A Include=""barbar"">
832                         <Prop1>bar_false</Prop1>
833                         <Prop2>bar_false</Prop2>
834                         <Prop3>bar value</Prop3>
835                 </A>
836
837         </ItemGroup>
838
839         <Target Name=""GetData"" Outputs=""@(AbcOutputs)"">
840                 <CreateItem Include=""@(A)"">
841                         <Output TaskParameter=""Include"" ItemName=""AbcOutputs""/>
842                 </CreateItem>
843         </Target>
844 </Project>
845 ";
846                         string secondProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
847         <ItemGroup>
848                 <A Include=""from_second"">
849                         <Prop1>false</Prop1>
850                         <Prop2>false</Prop2>
851                         <Prop3>new value</Prop3>
852                 </A>
853         </ItemGroup>
854
855         <Target Name=""GetData"" Outputs=""@(AbcOutputs)"">
856                 <CreateItem Include=""@(A)"">
857                         <Output TaskParameter=""Include"" ItemName=""AbcOutputs""/>
858                 </CreateItem>
859         </Target>
860 </Project>
861 ";
862
863                         CreateAndCheckGlobalPropertiesTest (mainProject, firstProject, secondProject,
864                                 null, null,
865                                 4, 3, 13,
866                                 new string [] {
867                                         "foofoo;barbar: F.Unique: true",
868                                         "foofoo;barbar: F.Unique: false",
869                                         "from_second: F.Unique: unique",
870                                         "foofoo;foofoo;from_second: F.Prop1: false",
871                                         "barbar;barbar: F.Prop1: bar_false",
872                                         "foofoo;foofoo;from_second: F.Prop2: false",
873                                         "barbar;barbar: F.Prop2: bar_false",
874                                         "foofoo;foofoo: F.Prop3: foo value",
875                                         "barbar;barbar: F.Prop3: bar value",
876                                         "from_second: F.Prop3: new value",
877                                 });
878                 }
879
880                 [Test]
881                 public void TestGetLoadedProject1()
882                 {
883                         Project project = Engine.GlobalEngine.GetLoadedProject("foo.proj");
884                         Assert.IsNull(project);
885                 }
886
887                 void CreateAndCheckGlobalPropertiesImportTest (string main, string first)
888                 {
889                         string basePath = Path.Combine ("Test", "resources");
890
891                         string testProject = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
892 </Project>";
893
894                         File.WriteAllText (Path.Combine (basePath, "main.proj"), main);
895                         File.WriteAllText (Path.Combine (basePath, "first.proj"), first);
896                         File.WriteAllText (Path.Combine (basePath, "test.proj"), testProject);
897
898                         try {
899                                 Engine engine = new Engine ();
900                                 MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
901                                         new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
902                                 engine.RegisterLogger (logger);
903
904                                 Project project = engine.CreateNewProject ();
905                                 project.Load (Path.Combine (basePath, "main.proj"));
906
907                                 bool result = project.Build ();
908                                 if (!result) {
909                                         logger.DumpMessages ();
910                                         Assert.Fail ("Build failed");
911                                 }
912
913                                 logger.CheckAny ("Prop: test", MessageImportance.Normal);
914                                 Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
915                         } finally {
916                                 File.Delete (Path.Combine (basePath, "main.proj"));
917                                 File.Delete (Path.Combine (basePath, "first.proj"));
918                                 File.Delete (Path.Combine (basePath, "test.proj"));
919                         }
920                 }
921
922                 // Helper Methods for TestGlobalProperties*
923
924                 void CreateAndCheckGlobalPropertiesTest (string main, string first, string second,
925                         int project_count, int target_count, int task_count, string [] messages)
926                 {
927                         CreateAndCheckGlobalPropertiesTest (main, first, second, null, null,
928                                 project_count, target_count, task_count, messages);
929                 }
930
931                 void CreateAndCheckGlobalPropertiesTest (string main, string first, string second,
932                         BuildPropertyGroup engine_globals, BuildPropertyGroup project_globals,
933                         int project_count, int target_count, int task_count, string [] messages)
934                 {
935                         WriteGlobalPropertiesProjects (main, first, second);
936
937                         Engine engine = new Engine (Consts.BinPath);
938                         if (engine_globals != null)
939                                 engine.GlobalProperties = engine_globals;
940                         MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
941                                 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
942                         engine.RegisterLogger (logger);
943
944                         Project project = engine.CreateNewProject ();
945                         project.Load (Path.Combine ("Test", Path.Combine ("resources", "main.proj")));
946                         if (project_globals != null)
947                                 project.GlobalProperties = project_globals;
948
949                         bool result = project.Build ();
950                         if (!result) {
951                                 logger.DumpMessages ();
952                                 Assert.Fail ("Build failed");
953                         }
954
955                         CheckEventCounts (logger, project_count, target_count, task_count);
956
957                         CheckLoggedMessages (logger, messages, "A1");
958                 }
959
960                 void CheckEventCounts (MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger,
961                         int project, int target, int task)
962                 {
963                         try {
964                                 Assert.AreEqual (project, logger.ProjectStarted, "#project started events");
965                                 Assert.AreEqual (project, logger.ProjectFinished, "#project finished events");
966                                 Assert.AreEqual (target, logger.TargetStarted, "#target started events");
967                                 Assert.AreEqual (target, logger.TargetFinished, "#target finished events");
968                                 Assert.AreEqual (task, logger.TaskStarted, "#task started events");
969                                 Assert.AreEqual (task, logger.TaskFinished, "#task finished events");
970                                 Assert.AreEqual (1, logger.BuildStarted, "#build started events");
971                                 Assert.AreEqual (1, logger.BuildFinished, "#build finished events");
972                         } catch (AssertionException) {
973                                 logger.DumpMessages ();
974                                 throw;
975                         }
976                 }
977
978                 void CheckLoggedMessages (MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger, string [] messages,
979                         string prefix)
980                 {
981                         try {
982                                 for (int i = 0; i < messages.Length; i++) {
983                                         logger.CheckLoggedMessageHead (messages [i], String.Format ("{0} #{1}", prefix, i));
984                                 }
985                         } catch {
986                                 logger.DumpMessages ();
987                                 throw;
988                         }
989
990                         Assert.AreEqual (0, logger.NormalMessageCount, "Number of remaining messages");
991                 }
992
993                 // helper methods for TestGlobalProperties*
994                 void WriteGlobalPropertiesProjects (string mainProject, string firstProject, string secondProject)
995                 {
996                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "main.proj")))) {
997                                 sw.Write (mainProject);
998                         }
999
1000                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "first.proj")))) {
1001                                 sw.Write (firstProject);
1002                         }
1003
1004                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "second.proj")))) {
1005                                 sw.Write (secondProject);
1006                         }
1007                 }
1008
1009                 public static string GetUsingTask (string taskName)
1010                 {
1011                         return "<UsingTask TaskName='Microsoft.Build.Tasks." + taskName + "' AssemblyFile='" + Consts.GetTasksAsmPath () + "' />";
1012                 }
1013         }
1014 }