5 // Marek Sieradzki (marek.sieradzki@gmail.com)
6 // Andres G. Aragoneses (knocte@gmail.com)
8 // (C) 2006 Marek Sieradzki
9 // (C) 2012 Andres G. Aragoneses
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using Microsoft.Build.BuildEngine;
32 using Microsoft.Build.Framework;
33 using Microsoft.Build.Utilities;
34 using MonoTests.Microsoft.Build.Tasks;
35 using NUnit.Framework;
39 namespace MonoTests.Microsoft.Build.BuildEngine {
41 public class TargetTest {
47 public void TestFromXml1 ()
49 string documentString = @"
50 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
51 <Target Name='Target'>
56 engine = new Engine (Consts.BinPath);
58 project = engine.CreateNewProject ();
59 project.LoadXml (documentString);
61 Target[] t = new Target [1];
62 project.Targets.CopyTo (t, 0);
64 Assert.AreEqual (String.Empty, t [0].Condition, "A1");
65 Assert.AreEqual (String.Empty, t [0].DependsOnTargets, "A2");
66 Assert.IsFalse (t [0].IsImported, "A3");
67 Assert.AreEqual ("Target", t [0].Name, "A4");
71 public void TestFromXml2 ()
73 string documentString = @"
74 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
75 <Target Name='Target' Condition='false' DependsOnTargets='X' >
80 engine = new Engine (Consts.BinPath);
82 project = engine.CreateNewProject ();
83 project.LoadXml (documentString);
85 Target[] t = new Target [1];
86 project.Targets.CopyTo (t, 0);
88 Assert.AreEqual ("false", t [0].Condition, "A1");
89 Assert.AreEqual ("X", t [0].DependsOnTargets, "A2");
91 t [0].Condition = "true";
92 t [0].DependsOnTargets = "A;B";
94 Assert.AreEqual ("true", t [0].Condition, "A3");
95 Assert.AreEqual ("A;B", t [0].DependsOnTargets, "A4");
99 public void TestAddNewTask1 ()
101 string documentString = @"
102 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
103 <Target Name='Target' >
108 engine = new Engine (Consts.BinPath);
110 project = engine.CreateNewProject ();
111 project.LoadXml (documentString);
113 Target[] t = new Target [1];
114 project.Targets.CopyTo (t, 0);
116 BuildTask bt = t [0].AddNewTask ("Message");
118 Assert.AreEqual ("Message", bt.Name, "A1");
122 [ExpectedException (typeof (ArgumentNullException))]
123 public void TestAddNewTask2 ()
125 string documentString = @"
126 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
127 <Target Name='Target' >
132 engine = new Engine (Consts.BinPath);
134 project = engine.CreateNewProject ();
135 project.LoadXml (documentString);
137 Target[] t = new Target [1];
138 project.Targets.CopyTo (t, 0);
140 t [0].AddNewTask (null);
144 public void TestGetEnumerator ()
146 string documentString = @"
147 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
148 <Target Name='Target' >
149 <Message Text='text' />
150 <Warning Text='text' />
155 engine = new Engine (Consts.BinPath);
157 project = engine.CreateNewProject ();
158 project.LoadXml (documentString);
160 Target[] t = new Target [1];
161 project.Targets.CopyTo (t, 0);
163 IEnumerator e = t [0].GetEnumerator ();
165 Assert.AreEqual ("Message", ((BuildTask) e.Current).Name, "A1");
167 Assert.AreEqual ("Warning", ((BuildTask) e.Current).Name, "A2");
168 Assert.IsFalse (e.MoveNext (), "A3");
172 public void TestOutOfRangeElementsOfTheEnumerator()
174 string documentString =
176 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
178 <Message Text='text' />
182 engine = new Engine (Consts.BinPath);
184 project = engine.CreateNewProject ();
185 project.LoadXml (documentString);
187 Assert.IsFalse (project.Targets == null, "A1");
188 Assert.AreEqual (1, project.Targets.Count, "A2");
190 Target target = project.Targets ["A"];
191 Assert.IsFalse (target == null, "A3");
193 IEnumerator e = target.GetEnumerator ();
197 var name = ((BuildTask)e.Current).Name;
198 } catch (InvalidOperationException) { // "Enumeration has not started. Call MoveNext"
202 Assert.Fail ("A4: Should have thrown IOE");
205 Assert.AreEqual (true, e.MoveNext (), "A5");
206 Assert.AreEqual ("Message", ((BuildTask)e.Current).Name, "A6");
207 Assert.AreEqual (false, e.MoveNext (), "A7");
209 var name = ((BuildTask) e.Current).Name;
210 } catch (InvalidOperationException) { //"Enumeration already finished."
213 Assert.Fail ("A8: Should have thrown IOE, because there's only one buidTask");
217 [ExpectedException (typeof (InvalidProjectFileException))]
218 public void TestOnError1 ()
223 string documentString = @"
224 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
226 <OnError ExecuteTargets='B' />
227 <Error Text='text' />
232 engine = new Engine (Consts.BinPath);
233 project = engine.CreateNewProject ();
234 project.LoadXml (documentString);
238 public void TestRemoveTask1 ()
240 string documentString = @"
241 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
242 <Target Name='Target' >
243 <Message Text='text' />
244 <Warning Text='text' />
249 engine = new Engine (Consts.BinPath);
251 project = engine.CreateNewProject ();
252 project.LoadXml (documentString);
254 Target[] t = new Target [1];
255 project.Targets.CopyTo (t, 0);
257 IEnumerator e = t [0].GetEnumerator ();
259 t [0].RemoveTask ((BuildTask) e.Current);
260 e = t [0].GetEnumerator ();
262 Assert.AreEqual ("Warning", ((BuildTask) e.Current).Name, "A1");
263 Assert.IsFalse (e.MoveNext (), "A2");
267 [ExpectedException (typeof (ArgumentNullException))]
268 public void TestRemoveTask2 ()
270 string documentString = @"
271 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
272 <Target Name='Target' >
277 engine = new Engine (Consts.BinPath);
279 project = engine.CreateNewProject ();
280 project.LoadXml (documentString);
282 Target[] t = new Target [1];
283 project.Targets.CopyTo (t, 0);
284 t [0].RemoveTask (null);
288 public void TestTargetOutputs1 ()
293 string documentString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
295 <fruit Include=""apple""/>
296 <fruit Include=""rhubarb""/>
297 <fruit Include=""apricot""/>
300 <Target Name=""Main"">
301 <CallTarget Targets=""foo"">
302 <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
305 <CallTarget Targets=""foo"">
306 <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
308 <Message Text=""AllOut: @(AllOut)""/>
311 <Target Name=""foo"" Outputs=""@(FooItem)"">
312 <Message Text=""foo called""/>
313 <CreateItem Include=""%(fruit.Identity)"">
314 <Output TaskParameter=""Include"" ItemName=""FooItem""/>
316 <Message Text=""FooItem: @(FooItem)""/>
320 engine = new Engine (Consts.BinPath);
321 project = engine.CreateNewProject ();
322 project.LoadXml (documentString);
324 MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
325 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
326 engine.RegisterLogger (logger);
328 bool result = project.Build ("Main");
330 logger.DumpMessages ();
331 Assert.Fail ("Build failed");
335 Assert.AreEqual (3, logger.NormalMessageCount, "Expected number of messages");
336 logger.CheckLoggedMessageHead ("foo called", "A1");
337 logger.CheckLoggedMessageHead ("FooItem: apple;rhubarb;apricot", "A2");
338 logger.CheckLoggedMessageHead ("AllOut: apple;rhubarb;apricot;apple;rhubarb;apricot", "A3");
339 Assert.AreEqual (0, logger.NormalMessageCount, "Extra messages found");
341 Assert.AreEqual (2, logger.TargetStarted, "TargetStarted count");
342 Assert.AreEqual (2, logger.TargetFinished, "TargetFinished count");
343 Assert.AreEqual (8, logger.TaskStarted, "TaskStarted count");
344 Assert.AreEqual (8, logger.TaskFinished, "TaskFinished count");
346 } catch (AssertionException) {
347 logger.DumpMessages ();
353 bool Build (string projectXml, ILogger logger)
355 if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
356 var reader = new StringReader (projectXml);
357 var xml = XmlReader.Create (reader);
358 return BuildOnWindows (xml, logger);
360 return BuildOnLinux (projectXml, logger);
364 bool BuildOnWindows (XmlReader reader, ILogger logger)
366 var type = Type.GetType ("Microsoft.Build.Evaluation.ProjectCollection, Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
368 var prop = type.GetProperty ("GlobalProjectCollection");
369 var coll = prop.GetValue (null);
371 var loadProject = coll.GetType ().GetMethod (
372 "LoadProject", new Type[] { typeof (XmlReader), typeof (string) });
373 var proj = loadProject.Invoke (coll, new object[] { reader, "4.0" });
375 var build = proj.GetType ().GetMethod ("Build", new Type[] { typeof (string), typeof (ILogger[]) });
376 var ret = (bool)build.Invoke (proj, new object[] { "Main", new ILogger[] { logger }});
380 bool BuildOnLinux (string projectXml, ILogger logger)
382 var engine = new Engine (Consts.BinPath);
383 var project = engine.CreateNewProject ();
384 project.LoadXml (projectXml);
386 engine.RegisterLogger (logger);
388 return project.Build ("Main");
391 TestMessageLogger CreateLogger (string projectXml)
393 var logger = new TestMessageLogger ();
394 var result = Build (projectXml, logger);
397 logger.DumpMessages ();
398 Assert.Fail ("Build failed");
404 void ItemGroupInsideTarget (string xml, params string[] messages)
406 var logger = CreateLogger (xml);
410 Assert.AreEqual(messages.Length, logger.NormalMessageCount, "Expected number of messages");
411 for (int i = 0; i < messages.Length; i++)
412 logger.CheckLoggedMessageHead (messages [i], i.ToString ());
413 Assert.AreEqual(0, logger.NormalMessageCount, "Extra messages found");
415 Assert.AreEqual(1, logger.TargetStarted, "TargetStarted count");
416 Assert.AreEqual(1, logger.TargetFinished, "TargetFinished count");
417 Assert.AreEqual(messages.Length, logger.TaskStarted, "TaskStarted count");
418 Assert.AreEqual(messages.Length, logger.TaskFinished, "TaskFinished count");
420 catch (AssertionException)
422 logger.DumpMessages();
428 public void BuildProjectWithItemGroupInsideTarget ()
430 ItemGroupInsideTarget (
431 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
433 <fruit Include=""apple""/>
434 <fruit Include=""apricot""/>
437 <Target Name=""Main"">
439 <fruit Include=""raspberry"" />
441 <Message Text=""%(fruit.Identity)""/>
443 </Project>", "apple", "apricot", "raspberry");
447 public void BuildProjectWithItemGroupInsideTarget2 ()
449 ItemGroupInsideTarget (
450 @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""4.0"">
463 <Sub>$(Foo);Hello</Sub>
467 <Message Text='@(A)' />
468 <Message Text='%(A.Sub)' />
470 </Project>", "1;2", "Foo", "Bar;Hello");
474 public void BuildProjectWithPropertyGroupInsideTarget ()
476 ItemGroupInsideTarget (
477 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
483 <Target Name=""Main"">
484 <Message Text='$(A)' />
488 <Message Text='$(A)' />
490 </Project>", "Foo", "Bar");
494 public void BuildProjectWithPropertyGroupInsideTarget2 ()
496 ItemGroupInsideTarget (
497 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
503 <Target Name=""Main"">
504 <Message Text='$(A)' />
505 <PropertyGroup Condition='true'>
506 <B Condition='false'>False</B>
508 <PropertyGroup Condition='true'>
511 <Message Text='$(A)' />
512 <Message Text='$(B)' />
514 <A Condition='$(A) == $(B)'>Equal</A>
516 <Message Text='$(A)' />
518 </Project>", "Foo", "Bar", "Bar", "Equal");
522 public void ItemGroupInsideTarget_ModifyMetadata ()
524 ItemGroupInsideTarget (
525 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
527 <Server Include='Server1'>
528 <AdminContact>Mono</AdminContact>
530 <Server Include='Server2'>
531 <AdminContact>Mono</AdminContact>
533 <Server Include='Server3'>
534 <AdminContact>Root</AdminContact>
540 <Server Condition=""'%(Server.AdminContact)' == 'Mono'"">
541 <AdminContact>Monkey</AdminContact>
545 <Message Text='%(Server.Identity) : %(Server.AdminContact)' />
547 </Project>", "Server1 : Monkey", "Server2 : Monkey", "Server3 : Root");
551 public void ItemGroupInsideTarget_RemoveItem ()
553 ItemGroupInsideTarget (
554 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
556 <Foo Include='A;B;C;D' />
564 <Message Text='@(Foo)' />
566 </Project>", "A;C;D");
570 public void ItemGroupInsideTarget_DontKeepDuplicates ()
572 ItemGroupInsideTarget (
573 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
575 <Foo Include='A;B' />
580 <Hello>Boston</Hello>
586 <Foo Include='B;C;D' KeepDuplicates='false'>
587 <Hello>Boston</Hello>
591 <Message Text='@(Foo)' />
593 </Project>", "A;B;C;D;B;C");
597 public void ItemGroupInsideTarget_RemoveMetadata ()
599 ItemGroupInsideTarget (
600 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
607 <Hello>Boston</Hello>
619 <Bar Include='@(Foo)' RemoveMetadata='$(Foo)' />
621 <Hello>Monkey</Hello>
625 <Message Text='%(Bar.Identity)' Condition=""'%(Bar.Hello)' != ''""/>
631 public void ItemGroupInsideTarget_RemoveMetadata2 ()
633 ItemGroupInsideTarget (
634 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
641 <Hello>Boston</Hello>
653 <Foo RemoveMetadata='$(Foo)' />
655 <Hello>Monkey</Hello>
659 <Message Text='%(Foo.Identity)' Condition=""'%(Foo.Hello)' != ''""/>
665 public void ItemGroupInsideTarget_KeepMetadata ()
667 ItemGroupInsideTarget (
668 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
675 <Hello>Boston</Hello>
684 <Foo KeepMetadata='Test' />
686 <Hello>Monkey</Hello>
690 <Message Text='%(Foo.Identity)' Condition=""'%(Foo.Test)' != ''""/>
696 public void ItemGroupInsideTarget_Batching ()
698 ItemGroupInsideTarget (
699 @"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
702 <Foo Include='A;B' />
703 <All Include='%(Foo.Identity)' />
705 <Message Text='%(All.Identity)' />
707 </Project>", "A", "B");
711 public void ItemGroupInsideTarget_Condition ()
713 ItemGroupInsideTarget (
714 @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""4.0"">
716 <Summer>true</Summer>
719 <Weather Include='Sun;Rain' />
723 <ItemGroup Condition=""'$(Summer)' != 'true'"">
724 <Weather Include='Snow' />
726 <Message Text='%(Weather.Identity)' />
728 </Project>", "Sun", "Rain");
733 public void TestTargetOutputsIncludingMetadata ()
738 string documentString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
740 <fruit Include=""apple""><md>a</md></fruit>
741 <fruit Include=""rhubarb""><md>b</md></fruit>
742 <fruit Include=""apricot""><md>c</md></fruit>
745 <Target Name=""Main"">
746 <CallTarget Targets=""foo"">
747 <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
750 <CallTarget Targets=""foo"">
751 <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
753 <Message Text=""AllOut: @(AllOut) metadata: %(AllOut.md)""/>
756 <Target Name=""foo"" Outputs=""@(FooItem)"">
757 <Message Text=""foo called""/>
758 <CreateItem Include=""@(fruit)"">
759 <Output TaskParameter=""Include"" ItemName=""FooItem""/>
761 <Message Text=""FooItem: @(FooItem) metadata: %(FooItem.md)""/>
765 engine = new Engine (Consts.BinPath);
766 project = engine.CreateNewProject ();
767 project.LoadXml (documentString);
769 MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
770 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
771 engine.RegisterLogger (logger);
773 bool result = project.Build ("Main");
775 logger.DumpMessages ();
776 Assert.Fail ("Build failed");
780 logger.CheckLoggedMessageHead ("foo called", "A1");
781 logger.CheckLoggedMessageHead ("FooItem: apple metadata: a", "A2");
782 logger.CheckLoggedMessageHead ("FooItem: rhubarb metadata: b", "A3");
783 logger.CheckLoggedMessageHead ("FooItem: apricot metadata: c", "A4");
785 logger.CheckLoggedMessageHead ("AllOut: apple;apple metadata: a", "A5");
786 logger.CheckLoggedMessageHead ("AllOut: rhubarb;rhubarb metadata: b", "A6");
787 logger.CheckLoggedMessageHead ("AllOut: apricot;apricot metadata: c", "A7");
789 Assert.AreEqual (0, logger.NormalMessageCount, "Extra messages found");
791 Assert.AreEqual (2, logger.TargetStarted, "TargetStarted count");
792 Assert.AreEqual (2, logger.TargetFinished, "TargetFinished count");
793 Assert.AreEqual (10, logger.TaskStarted, "TaskStarted count");
794 Assert.AreEqual (10, logger.TaskFinished, "TaskFinished count");
796 } catch (AssertionException) {
797 logger.DumpMessages ();
803 public void TestOverridingTargets ()
808 string second = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
809 <Target Name='BeforeBuild'/>
810 <Target Name='AfterBuild'/>
811 <Target Name='Build' DependsOnTargets='BeforeBuild'>
812 <Message Text='Build executing'/>
813 <CallTarget Targets='AfterBuild'/>
816 using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "second.proj")))) {
820 string documentString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
821 <Target Name='AfterBuild'>
822 <Message Text='Overriding AfterBuild'/>
825 <Import Project='Test/resources/second.proj'/>
826 <Target Name='BeforeBuild'>
827 <Message Text='Overriding BeforeBuild'/>
831 engine = new Engine (Consts.BinPath);
832 project = engine.CreateNewProject ();
833 project.LoadXml (documentString);
835 MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
836 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
837 engine.RegisterLogger (logger);
839 bool result = project.Build ("Build");
841 logger.DumpMessages ();
842 Assert.Fail ("Build failed");
845 logger.CheckLoggedMessageHead ("Overriding BeforeBuild", "A1");
846 logger.CheckLoggedMessageHead ("Build executing", "A1");
848 Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
853 [Category ("NotDotNet")]
854 public void TestBeforeAndAfterTargets ()
859 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""4.0"">
860 <Target Name=""DefaultBeforeTarget1"" BeforeTargets=""Default"">
861 <Message Text=""Hello from DefaultBeforeTarget1""/>
864 <Target Name=""DefaultBeforeTarget2"" BeforeTargets=""Default;Default;NonExistant"">
865 <Message Text=""Hello from DefaultBeforeTarget2""/>
869 <Target Name=""DefaultAfterTarget"" AfterTargets=""Default ; Foo"">
870 <Message Text=""Hello from DefaultAfterTarget""/>
873 <Target Name=""Default"" DependsOnTargets=""DefaultDependsOn"">
874 <Message Text=""Hello from Default""/>
877 <Target Name=""DefaultDependsOn"">
878 <Message Text=""Hello from DefaultDependsOn""/>
882 engine = new Engine ();
883 project = engine.CreateNewProject ();
884 project.LoadXml (projectString);
886 MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
887 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
888 engine.RegisterLogger (logger);
890 if (!project.Build ("Default")) {
891 logger.DumpMessages ();
892 Assert.Fail ("Build failed");
895 logger.CheckLoggedMessageHead ("Hello from DefaultDependsOn", "A1");
896 logger.CheckLoggedMessageHead ("Hello from DefaultBeforeTarget1", "A1");
897 logger.CheckLoggedMessageHead ("Hello from DefaultBeforeTarget2", "A1");
898 logger.CheckLoggedMessageHead ("Hello from Default", "A1");
899 logger.CheckLoggedMessageHead ("Hello from DefaultAfterTarget", "A1");
901 Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected messages found");
903 //warnings for referencing unknown targets: NonExistant and Foo
904 Assert.AreEqual (2, logger.WarningsCount, "Expected warnings not raised");