5 // Ankit Jain (jankit@novell.com)
7 // Copyright 2008 Novell, Inc (http://www.novell.com)
8 // Copyright 2009 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Collections
.Generic
;
32 using NUnit
.Framework
;
33 using Microsoft
.Build
.BuildEngine
;
34 using Microsoft
.Build
.Framework
;
35 using Microsoft
.Build
.Tasks
;
36 using Microsoft
.Build
.Utilities
;
38 namespace MonoTests
.Microsoft
.Build
.Tasks
41 public class TaskBatchingTest
44 public TaskBatchingTest ()
46 projectHeader
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" " + Consts
.ToolsVersionString
+ ">";
52 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
54 <ResXFile Include=""Item1"">
57 <ResXFile Include=""Item2"">
60 <ResXFile Include=""Item3"">
63 <ResXFile Include=""Item4"">
66 <ResXFile Include=""Item5"">
69 <ResXFile Include=""Item6"">
74 <Target Name=""ShowMessage"">
76 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
80 Engine engine
= new Engine (Consts
.BinPath
);
81 Project project
= engine
.CreateNewProject ();
83 TestMessageLogger testLogger
= new TestMessageLogger ();
84 engine
.RegisterLogger (testLogger
);
86 project
.LoadXml (projectString
);
87 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
89 CheckMessage (testLogger
, "fr", "Item1;Item2;Item5", "A2");
90 CheckMessage (testLogger
, "en", "Item3", "A3");
91 CheckMessage (testLogger
, "gb", "Item4", "A4");
92 CheckMessage (testLogger
, "it", "Item6", "A5");
94 CheckEngineEventCounts (testLogger
, 1, 1, 4, 4);
97 // Test1 with unqualified %(Culture)
101 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
103 <ResXFile Include=""Item1"">
104 <Culture>fr</Culture>
106 <ResXFile Include=""Item2"">
107 <Culture>fr</Culture>
109 <ResXFile Include=""Item3"">
110 <Culture>en</Culture>
112 <ResXFile Include=""Item4"">
113 <Culture>gb</Culture>
115 <ResXFile Include=""Item5"">
116 <Culture>fr</Culture>
118 <ResXFile Include=""Item6"">
119 <Culture>it</Culture>
123 <Target Name=""ShowMessage"">
125 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
129 Engine engine
= new Engine (Consts
.BinPath
);
130 Project project
= engine
.CreateNewProject ();
132 TestMessageLogger testLogger
= new TestMessageLogger ();
133 engine
.RegisterLogger (testLogger
);
135 project
.LoadXml (projectString
);
136 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
138 CheckMessage (testLogger
, "fr", "Item1;Item2;Item5", "A2");
139 CheckMessage (testLogger
, "en", "Item3", "A3");
140 CheckMessage (testLogger
, "gb", "Item4", "A4");
141 CheckMessage (testLogger
, "it", "Item6", "A5");
143 CheckEngineEventCounts (testLogger
, 1, 1, 4, 4);
147 public void TestUnqualifiedMetadataReference ()
149 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
151 <ResXFile Include=""Item1"">
152 <Culture>fr</Culture>
154 <ResXFile Include=""Item5"" />
155 <ResXFile Include=""Item6"">
156 <Culture>it</Culture>
160 <Target Name=""ShowMessage"">
162 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
166 Engine engine
= new Engine (Consts
.BinPath
);
167 Project project
= engine
.CreateNewProject ();
169 TestMessageLogger testLogger
= new TestMessageLogger ();
170 engine
.RegisterLogger (testLogger
);
172 project
.LoadXml (projectString
);
174 //Fails as Culture is being referenced unqualified, and no Culture is
175 //specified for "Item5"
176 bool result
= project
.Build ("ShowMessage");
178 Assert
.Fail ("A1: Build should have failed");
180 CheckEngineEventCounts (testLogger
, 1, 1, 0, 0);
186 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
188 <ResXFile Include=""Item1"">
189 <Culture>fr</Culture>
191 <ResXFile Include=""Item5"" />
192 <ResXFile Include=""Item6"">
193 <Culture>it</Culture>
197 <Target Name=""ShowMessage"">
199 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
203 Engine engine
= new Engine (Consts
.BinPath
);
204 Project project
= engine
.CreateNewProject ();
206 TestMessageLogger testLogger
= new TestMessageLogger ();
207 engine
.RegisterLogger (testLogger
);
209 project
.LoadXml (projectString
);
211 //no Culture is specified for "Item5", but
212 //Culture is being referenced __qualified__, so works
213 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
215 CheckMessage (testLogger
, "fr", "Item1", "A2");
216 CheckMessage (testLogger
, "", "Item5", "A3");
217 CheckMessage (testLogger
, "it", "Item6", "A3");
218 CheckEngineEventCounts (testLogger
, 1, 1, 3, 3);
222 public void TestMultiItemCollections ()
224 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
226 <ResXFile Include=""Item1"">
227 <Culture>fr</Culture>
229 <ResXFile Include=""Item2"">
230 <Culture>fr</Culture>
232 <ResXFile Include=""Item3"">
233 <Culture>en</Culture>
235 <ResXFile Include=""Item4"">
236 <Culture>gb</Culture>
238 <ResXFile Include=""Item6"">
239 <Culture>it</Culture>
242 <NonResXFile Include=""Item7"">
243 <Culture>it</Culture>
245 <NonResXFile Include=""Item8"">
246 <Culture>en</Culture>
248 <NonResXFile Include=""Item9"">
249 <Culture>en</Culture>
253 <Target Name=""ShowMessage"">
255 Text = ""Culture: %(Culture) -- ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)"" />
259 Engine engine
= new Engine (Consts
.BinPath
);
260 Project project
= engine
.CreateNewProject ();
262 TestMessageLogger testLogger
= new TestMessageLogger ();
263 engine
.RegisterLogger (testLogger
);
265 project
.LoadXml (projectString
);
266 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
268 CheckMessage2 (testLogger
, "fr", "Item1;Item2", string.Empty
, "A2");
269 CheckMessage2 (testLogger
, "en", "Item3", "Item8;Item9", "A3");
270 CheckMessage2 (testLogger
, "gb", "Item4", string.Empty
, "A4");
271 CheckMessage2 (testLogger
, "it", "Item6", "Item7", "A6");
272 CheckEngineEventCounts (testLogger
, 1, 1, 4, 4);
276 public void TestConditionalBatching ()
278 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
280 <ResXFile Include=""Item1"">
281 <Culture>fr</Culture>
283 <ResXFile Include=""Item2"">
284 <Culture>fr</Culture>
286 <ResXFile Include=""Item3"">
287 <Culture>en</Culture>
289 <ResXFile Include=""Item4"">
290 <Culture>gb</Culture>
292 <ResXFile Include=""Item6"">
293 <Culture>it</Culture>
296 <NonResXFile Include=""Item7"">
297 <Culture>it</Culture>
299 <NonResXFile Include=""Item8"">
300 <Culture>en</Culture>
302 <NonResXFile Include=""Item9"">
303 <Culture>en</Culture>
307 <Target Name=""ShowMessage"">
309 Text = ""ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)""
310 Condition = ""'%(Culture)' == 'fr'""/>
314 Engine engine
= new Engine (Consts
.BinPath
);
315 Project project
= engine
.CreateNewProject ();
317 TestMessageLogger testLogger
= new TestMessageLogger ();
318 engine
.RegisterLogger (testLogger
);
320 project
.LoadXml (projectString
);
321 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
323 testLogger
.CheckLoggedMessageHead ("ResXFiles: Item1;Item2 NonResXFiles: ", "A2");
324 CheckEngineEventCounts (testLogger
, 1, 1, 1, 1);
328 public void TestMultipleMetadataReference ()
330 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
332 <ExampColl Include=""Item1"">
335 <ExampColl Include=""Item2"">
338 <ExampColl Include=""Item3"">
342 <ExampColl2 Include=""Item4"">
345 <ExampColl2 Include=""Item5"">
349 <ExampColl2 Include=""Item6"">
354 <Target Name=""ShowMessage"">
355 <Message Text = ""Number: %(Number) Color: %(ExampColl2.Color)-- Items in ExampColl: @(ExampColl) ExampColl2: @(ExampColl2)""/>
359 Engine engine
= new Engine (Consts
.BinPath
);
360 Project project
= engine
.CreateNewProject ();
362 TestMessageLogger testLogger
= new TestMessageLogger ();
363 engine
.RegisterLogger (testLogger
);
365 project
.LoadXml (projectString
);
366 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
368 CheckLoggedMessageAny (testLogger
, "Number: 1 Color: -- Items in ExampColl: Item1;Item3 ExampColl2: Item4", "A2");
369 CheckLoggedMessageAny (testLogger
, "Number: 2 Color: Red-- Items in ExampColl: ExampColl2: Item5", "A3");
370 CheckLoggedMessageAny (testLogger
, "Number: 3 Color: Green-- Items in ExampColl: ExampColl2: Item6", "A4");
371 CheckLoggedMessageAny (testLogger
, "Number: 2 Color: -- Items in ExampColl: Item2 ExampColl2: ", "A5");
372 Assert
.AreEqual (0, testLogger
.Count
, "A6");
373 CheckEngineEventCounts (testLogger
, 1, 1, 4, 4);
377 public void TestMultipleMetadataReference2 ()
379 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
381 <GroupA Include=""file1.txt""/>
382 <GroupA Include=""file2.txt""/>
383 <GroupA Include=""file3.txt""/>
384 <GroupA Include=""file3.txt""/>
385 <GroupA Include=""file4.txt""/>
389 <GroupB Include=""file1.txt""/>
390 <GroupB Include=""file3.txt""/>
391 <GroupB Include=""file5.txt""/>
393 <GroupC Include=""PreExistingValue""/>
396 <Target Name=""Build"">
397 <CreateItem Include=""@(GroupA)"" Condition=""'%(Identity)' != '' and '@(GroupA)' != '' and '@(GroupB)' != ''"" >
398 <Output TaskParameter=""Include"" ItemName=""GroupC""/>
400 <Message Text=""%(GroupC.Identity)""/>
404 Engine engine
= new Engine (Consts
.BinPath
);
405 Project project
= engine
.CreateNewProject ();
407 TestMessageLogger testLogger
= new TestMessageLogger ();
408 engine
.RegisterLogger (testLogger
);
410 project
.LoadXml (projectString
);
411 Assert
.IsTrue (project
.Build ("Build"), "A1: Build failed");
413 BuildItemGroup include
= project
.GetEvaluatedItemsByName ("GroupC");
414 Assert
.AreEqual (4, include
.Count
, "A2");
416 string [,] additional_metadata
= new string [,] { { "Identity", "PreExistingValue" }
};
417 CreateItemTest
.CheckBuildItem (include
[0], "GroupC", additional_metadata
, "PreExistingValue", "A3");
419 additional_metadata
= new string [,] { { "Identity", "file1.txt" }
};
420 CreateItemTest
.CheckBuildItem (include
[1], "GroupC", additional_metadata
, "file1.txt", "A4");
422 additional_metadata
= new string [,] { { "Identity", "file3.txt" }
};
423 CreateItemTest
.CheckBuildItem (include
[2], "GroupC", additional_metadata
, "file3.txt", "A5");
424 CreateItemTest
.CheckBuildItem (include
[3], "GroupC", additional_metadata
, "file3.txt", "A6");
426 CheckEngineEventCounts (testLogger
, 1, 1, 5, 5);
430 public void TestIdentity ()
432 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
434 <ExampColl Include=""Item1""/>
435 <ExampColl Include=""Item2""/>
436 <ExampColl Include=""Item3""/>
437 <ExampColl Include=""Item4""/>
438 <ExampColl Include=""Item4""/>
439 <ExampColl Include=""Item5""/>
440 <ExampColl Include=""Item6""/>
442 <Target Name=""ShowMessage"">
443 <Message Text = ""Identity: %(IdenTIty) -- Items in ExampColl: @(ExampColl)""/>
447 Engine engine
= new Engine (Consts
.BinPath
);
448 Project project
= engine
.CreateNewProject ();
450 TestMessageLogger testLogger
= new TestMessageLogger ();
451 engine
.RegisterLogger (testLogger
);
453 project
.LoadXml (projectString
);
454 Assert
.IsTrue (project
.Build ("ShowMessage"), "A1: Build failed");
456 CheckLoggedMessageAny (testLogger
, "Identity: Item1 -- Items in ExampColl: Item1", "A2");
457 CheckLoggedMessageAny (testLogger
, "Identity: Item2 -- Items in ExampColl: Item2", "A3");
458 CheckLoggedMessageAny (testLogger
, "Identity: Item3 -- Items in ExampColl: Item3", "A4");
459 CheckLoggedMessageAny (testLogger
, "Identity: Item4 -- Items in ExampColl: Item4;Item4", "A5");
460 CheckLoggedMessageAny (testLogger
, "Identity: Item5 -- Items in ExampColl: Item5", "A6");
461 CheckLoggedMessageAny (testLogger
, "Identity: Item6 -- Items in ExampColl: Item6", "A7");
462 Assert
.AreEqual (0, testLogger
.Count
, "A8");
463 CheckEngineEventCounts (testLogger
, 1, 1, 6, 6);
467 public void TestFilter ()
469 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
471 <fruit Include=""apple"">
472 <consistency>firm</consistency>
474 <fruit Include=""orange"">
475 <consistency>pulpy</consistency>
477 <fruit Include=""banana"">
478 <consistency>softish</consistency>
480 <fruit Include=""pear"">
481 <consistency>unsound</consistency>
483 <fruit Include=""apricot"">
484 <consistency>unsound</consistency>
487 <Target Name=""Compost"">
488 <CreateItem Include=""@(fruit)"" Condition=""'%(consistency)' == 'pulpy' or '%(consistency)' == 'unsound' "">
489 <Output TaskParameter=""Include"" ItemName=""Final""/>
494 Engine engine
= new Engine (Consts
.BinPath
);
495 Project project
= engine
.CreateNewProject ();
497 TestMessageLogger testLogger
= new TestMessageLogger ();
498 engine
.RegisterLogger (testLogger
);
500 project
.LoadXml (projectString
);
501 Assert
.IsTrue (project
.Build ("Compost"), "A1: Build failed");
503 BuildItemGroup include
= project
.GetEvaluatedItemsByName ("Final");
504 Assert
.AreEqual (3, include
.Count
, "A2");
506 string [,] additional_metadata
= new string [,] { { "Identity", "orange" }
};
507 CreateItemTest
.CheckBuildItem (include
[0], "Final", additional_metadata
, "orange", "A3");
509 additional_metadata
= new string [,] { { "Identity", "pear" }
};
510 CreateItemTest
.CheckBuildItem (include
[1], "Final", additional_metadata
, "pear", "A4");
512 additional_metadata
= new string [,] { { "Identity", "apricot" }
};
513 CreateItemTest
.CheckBuildItem (include
[2], "Final", additional_metadata
, "apricot", "A5");
514 CheckEngineEventCounts (testLogger
, 1, 1, 2, 2);
518 // test for metadata refs in properties or items
519 public void TestNoBatching () {
520 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
522 <item3 Include=""foo""/>
523 <item2 Include=""%(item3.Identity)""/>
524 <item0 Include=""@(item3)""/>
527 <Prop1>%(item0.Identity)</Prop1>
530 <Message Text=""Prop1: $(Prop1)""/>
531 <Message Text=""Item2: @(item2)""/>
535 Engine engine
= new Engine (Consts
.BinPath
);
536 Project project
= engine
.CreateNewProject ();
538 TestMessageLogger testLogger
= new TestMessageLogger ();
539 engine
.RegisterLogger (testLogger
);
541 project
.LoadXml (projectString
);
542 if (!project
.Build ("1")) {
543 testLogger
.DumpMessages ();
544 Assert
.Fail ("Build failed");
547 testLogger
.CheckLoggedMessageHead ("Prop1: %(item0.Identity)", "A1");
548 testLogger
.CheckLoggedMessageHead ("Item2: %(item3.Identity)", "A2");
549 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
553 // test for metadata refs via metadata refs
554 // batching should happen only on basis of the task attributes,
555 // and not the resolved expression values
556 public void TestBatching1 () {
557 string projectString
= projectHeader
+ @"
559 <item3 Include=""foo""/>
560 <item2 Include=""%(item3.Identity)""/>
562 <item4 Include=""%(item2.Identity);@(item3);@(nonexistant)""/>
563 <item4 Include=""bar""/>
566 <Message Text=""Item4: %(item4.Identity)""/>
570 Engine engine
= new Engine (Consts
.BinPath
);
571 Project project
= engine
.CreateNewProject ();
573 TestMessageLogger testLogger
= new TestMessageLogger ();
574 engine
.RegisterLogger (testLogger
);
576 project
.LoadXml (projectString
);
577 if (!project
.Build ("1")) {
578 testLogger
.DumpMessages ();
579 Assert
.Fail ("Build failed");
582 testLogger
.CheckLoggedMessageHead ("Item4: %(item2.Identity)", "A1");
583 testLogger
.CheckLoggedMessageHead ("Item4: foo", "A2");
584 testLogger
.CheckLoggedMessageHead ("Item4: bar", "A3");
585 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
589 // test for metadata refs via metadata refs
590 // batching should happen only on basis of the task attributes,
591 // and not the resolved expression values
592 public void TestConditionalBatching2 () {
593 string projectString
= projectHeader
+ @"
595 <item2 Include=""%(item3.Identity)""/>
596 <item4 Include=""%(item2.Identity);@(item3)""/>
599 <Message Text=""Item3: %(item2.Identity)"" Condition="" '%(item5.Identity)' == '' ""/>
600 <Message Text=""Item4: %(item4.Identity)""/>
604 Engine engine
= new Engine (Consts
.BinPath
);
605 Project project
= engine
.CreateNewProject ();
607 TestMessageLogger testLogger
= new TestMessageLogger ();
608 engine
.RegisterLogger (testLogger
);
610 project
.LoadXml (projectString
);
611 if (!project
.Build ("1")) {
612 testLogger
.DumpMessages ();
613 Assert
.Fail ("Build failed");
616 testLogger
.CheckLoggedMessageHead ("Item3: %(item3.Identity)", "A1");
617 testLogger
.CheckLoggedMessageHead ("Item4: %(item2.Identity)", "A2");
618 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
622 public void TestBatchingWithUnbatchedItems () {
623 string projectString
= projectHeader
+ @"
625 <Item1 Include=""One""/>
626 <Item1 Include=""Two""/>
631 <Message Text=""Item1: %(Item1.Identity) | B: @(B)""/>
635 Engine engine
= new Engine (Consts
.BinPath
);
636 Project project
= engine
.CreateNewProject ();
638 TestMessageLogger testLogger
= new TestMessageLogger ();
639 engine
.RegisterLogger (testLogger
);
641 project
.LoadXml (projectString
);
642 if (!project
.Build ("1")) {
643 testLogger
.DumpMessages ();
644 Assert
.Fail ("Build failed");
648 testLogger
.CheckLoggedMessageHead ("Item1: One | B: abc", "A1");
649 testLogger
.CheckLoggedMessageHead ("Item1: Two | B: abc", "A2");
651 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
652 } catch (AssertionException
) {
653 testLogger
.DumpMessages ();
659 public void TestPropertiesWithBatchedReferences () {
660 string projectString
= projectHeader
+ @"
662 <Item1 Include=""One""/>
663 <Item1 Include=""Two""/>
665 <Item1Ref Include=""@(Item1)""/>
668 <Prop1>@(Item1)</Prop1>
669 <Prop2>@(Item1Ref)</Prop2>
672 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
676 Engine engine
= new Engine (Consts
.BinPath
);
677 Project project
= engine
.CreateNewProject ();
679 TestMessageLogger testLogger
= new TestMessageLogger ();
680 engine
.RegisterLogger (testLogger
);
682 project
.LoadXml (projectString
);
683 if (!project
.Build ("1")) {
685 testLogger
.DumpMessages ();
686 Assert
.Fail ("Build failed");
690 testLogger
.CheckLoggedMessageHead ("Item1: One | Prop1: One | Prop2: One;Two", "A1");
691 testLogger
.CheckLoggedMessageHead ("Item1: Two | Prop1: Two | Prop2: One;Two", "A2");
693 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
694 } catch (AssertionException
) {
695 testLogger
.DumpMessages ();
701 public void TestPropertiesWithDynamicItems () {
702 string projectString
= projectHeader
+ @"
704 <Item1 Include=""One""/>
705 <Item1 Include=""Two""/>
707 <Item2 Include=""Z""/>
708 <Item2Ref Include=""@(Item2)"" />
711 <Prop1>@(Item2)</Prop1>
712 <Prop2>@(Item2Ref)</Prop2>
715 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
716 <Message Text=""Item2: @(Item2) | Item2Ref: @(Item2Ref)""/>
717 <CreateItem Include=""A;B"">
718 <Output TaskParameter=""Include"" ItemName=""Item2""/>
720 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
721 <Message Text=""Item2: @(Item2) | Item2Ref: @(Item2Ref)""/>
725 Engine engine
= new Engine (Consts
.BinPath
);
726 Project project
= engine
.CreateNewProject ();
728 TestMessageLogger testLogger
= new TestMessageLogger ();
729 engine
.RegisterLogger (testLogger
);
731 project
.LoadXml (projectString
);
732 if (!project
.Build ("1")) {
734 testLogger
.DumpMessages ();
735 Assert
.Fail ("Build failed");
740 testLogger
.CheckLoggedMessageHead ("Item1: One | Prop1: Z | Prop2: Z", "A1");
741 testLogger
.CheckLoggedMessageHead ("Item1: Two | Prop1: Z | Prop2: Z", "A2");
742 testLogger
.CheckLoggedMessageHead ("Item2: Z | Item2Ref: Z", "A3");
744 testLogger
.CheckLoggedMessageHead ("Item1: One | Prop1: Z;A;B | Prop2: Z", "A4");
745 testLogger
.CheckLoggedMessageHead ("Item1: Two | Prop1: Z;A;B | Prop2: Z", "A5");
746 testLogger
.CheckLoggedMessageHead ("Item2: Z;A;B | Item2Ref: Z", "A3");
748 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
749 } catch (AssertionException
) {
750 testLogger
.DumpMessages ();
756 public void TestTargetInvocationFromBatchedTask () {
757 string projectString
= projectHeader
+ @"
759 <Item1 Include=""One""/>
760 <Item1 Include=""Two""/>
762 <Item1Ref Include=""@(Item1)"" />
765 <Prop1>@(Item1)</Prop1>
766 <Prop2>@(Item1Ref)</Prop2>
769 <CallTarget Targets='foo' Condition="" '%(Item1.Identity)' != ''"" />
770 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
771 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
774 <Message Text=""(foo) Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
775 <Message Text=""(foo) Prop1: $(Prop1) Prop2: $(Prop2)""/>
779 Engine engine
= new Engine (Consts
.BinPath
);
780 Project project
= engine
.CreateNewProject ();
782 TestMessageLogger testLogger
= new TestMessageLogger ();
783 engine
.RegisterLogger (testLogger
);
785 project
.LoadXml (projectString
);
786 if (!project
.Build ("1")) {
788 testLogger
.DumpMessages ();
789 Assert
.Fail ("Build failed");
793 testLogger
.CheckLoggedMessageHead ("(foo) Item1: One;Two Item1Ref: One;Two", "A1");
794 testLogger
.CheckLoggedMessageHead ("(foo) Prop1: One;Two Prop2: One;Two", "A2");
796 testLogger
.CheckLoggedMessageHead ("Item1: One;Two Item1Ref: One;Two", "A3");
797 testLogger
.CheckLoggedMessageHead ("Prop1: One;Two Prop2: One;Two", "A4");
799 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
800 } catch (AssertionException
) {
801 testLogger
.DumpMessages ();
807 public void TestTargetInvocationFromBatchedTarget () {
808 string projectString
= projectHeader
+ @"
810 <Item1 Include=""One""/>
811 <Item1 Include=""Two""/>
813 <Item1Ref Include=""@(Item1)"" />
816 <Prop1>@(Item1)</Prop1>
817 <Prop2>@(Item1Ref)</Prop2>
819 <Target Name='1' Inputs=""%(Item1.Identity)"" Outputs=""Nonexistant.foobar"">
820 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
821 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
823 <CallTarget Targets='foo' />
825 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
826 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
828 <Target Name='foo' Condition="" '@(Item1)' != 'One' "">
829 <Message Text=""(foo) Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
830 <Message Text=""(foo) Prop1: $(Prop1) Prop2: $(Prop2)""/>
834 Engine engine
= new Engine (Consts
.BinPath
);
835 Project project
= engine
.CreateNewProject ();
837 TestMessageLogger testLogger
= new TestMessageLogger ();
838 engine
.RegisterLogger (testLogger
);
840 project
.LoadXml (projectString
);
841 if (!project
.Build ("1")) {
843 testLogger
.DumpMessages ();
844 Assert
.Fail ("Build failed");
848 testLogger
.CheckLoggedMessageHead ("Item1: One Item1Ref: One;Two", "A1");
849 testLogger
.CheckLoggedMessageHead ("Prop1: One Prop2: One;Two", "A2");
851 testLogger
.CheckLoggedMessageHead ("(foo) Item1: One;Two Item1Ref: One;Two", "A3");
852 testLogger
.CheckLoggedMessageHead ("(foo) Prop1: One;Two Prop2: One;Two", "A4");
854 testLogger
.CheckLoggedMessageHead ("Item1: One Item1Ref: One;Two", "A5");
855 testLogger
.CheckLoggedMessageHead ("Prop1: One Prop2: One;Two", "A6");
857 //second batch, foo has already run, so doesn't execute again
858 testLogger
.CheckLoggedMessageHead ("Item1: Two Item1Ref: One;Two", "A7");
859 testLogger
.CheckLoggedMessageHead ("Prop1: Two Prop2: One;Two", "A8");
861 testLogger
.CheckLoggedMessageHead ("Item1: Two Item1Ref: One;Two", "A9");
862 testLogger
.CheckLoggedMessageHead ("Prop1: Two Prop2: One;Two", "A10");
864 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
865 } catch (AssertionException
) {
866 testLogger
.DumpMessages ();
872 public void TestBatchingWithUnqualifiedMetadataReference () {
873 string projectString
= projectHeader
+ @"
875 <Item1 Include=""One""><Md>1</Md></Item1>
876 <Item1 Include=""Two""><Md>2</Md></Item1>
877 <Item1Ref Include=""@(Item1)"" />
879 <Item2 Include=""Three""><Md>3</Md></Item2>
880 <Item2 Include=""Four""><Md>4</Md></Item2>
881 <Item2Ref Include=""@(Item2)"" />
884 <Prop1>@(Item1)</Prop1>
885 <Prop1Ref>@(Item1Ref)</Prop1Ref>
887 <Prop2>@(Item2)</Prop2>
888 <Prop2Ref>@(Item2Ref)</Prop2Ref>
891 <Message Text=""For md: %(Md) Item1: @(Item1) Item1Ref: @(Item1Ref) Item2: @(Item2) Item2Ref: @(Item2Ref) " +
892 @" Prop1: $(Prop1) Prop1Ref: $(Prop1Ref) Prop2: $(Prop2) Prop2Ref: $(Prop2Ref)""/>
896 Engine engine
= new Engine (Consts
.BinPath
);
897 Project project
= engine
.CreateNewProject ();
899 TestMessageLogger testLogger
= new TestMessageLogger ();
900 engine
.RegisterLogger (testLogger
);
902 project
.LoadXml (projectString
);
903 if (!project
.Build ("1")) {
905 testLogger
.DumpMessages ();
906 Assert
.Fail ("Build failed");
908 testLogger
.DumpMessages ();
911 testLogger
.CheckLoggedAny ("For md: 3 Item1: Item1Ref: Item2: Three Item2Ref: Three Prop1: Prop1Ref: Prop2: Three Prop2Ref: Three", MessageImportance
.Normal
, "A1");
912 testLogger
.CheckLoggedAny ("For md: 4 Item1: Item1Ref: Item2: Four Item2Ref: Four Prop1: Prop1Ref: Prop2: Four Prop2Ref: Four", MessageImportance
.Normal
, "A2");
913 testLogger
.CheckLoggedAny ("For md: 1 Item1: One Item1Ref: One Item2: Item2Ref: Prop1: One Prop1Ref: One Prop2: Prop2Ref: ", MessageImportance
.Normal
, "A3");
914 testLogger
.CheckLoggedAny ("For md: 2 Item1: Two Item1Ref: Two Item2: Item2Ref: Prop1: Two Prop1Ref: Two Prop2: Prop2Ref: ", MessageImportance
.Normal
, "A4");
916 Assert
.AreEqual (0, testLogger
.NormalMessageCount
, "Unexpected extra messages found");
917 } catch (AssertionException
) {
918 testLogger
.DumpMessages ();
927 public void TestTargetBatching1 ()
929 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
931 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
932 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
933 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
934 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
936 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
937 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
939 <Foo Include=""1_a1""><Md>1</Md></Foo>
940 <Foo Include=""2_b1""><Md>2</Md></Foo>
941 <Foo Include=""1_c1""><Md>1</Md></Foo>
944 <Target Name=""foo"" >
945 <Message Text=""TargetStarted""/>
946 <Message Text=""List1: @(List1): %(Culture)""/>
947 <Message Text=""Foo: @(Foo): %(Md)""/>
951 Engine engine
= new Engine (Consts
.BinPath
);
952 Project project
= engine
.CreateNewProject ();
954 TestMessageLogger testLogger
= new TestMessageLogger ();
955 engine
.RegisterLogger (testLogger
);
957 project
.LoadXml (projectString
);
958 bool res
= project
.Build ("foo");
960 testLogger
.DumpMessages ();
961 Assert
.Fail ("A1: Build failed");
964 CheckLoggedMessagesInOrder (testLogger
, new string [] {
965 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
966 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
967 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
969 CheckEngineEventCounts (testLogger
, 1, 1, 6, 6);
973 public void TestTargetBatching2 ()
975 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
977 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
978 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
979 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
980 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
982 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
983 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
985 <Foo Include=""1_a1""><Md>1</Md></Foo>
986 <Foo Include=""2_b1""><Md>2</Md></Foo>
987 <Foo Include=""1_c1""><Md>1</Md></Foo>
990 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
991 <Message Text=""TargetStarted""/>
992 <Message Text=""List1: @(List1): %(Culture)""/>
993 <Message Text=""Foo: @(Foo): %(Md)""/>
997 Engine engine
= new Engine (Consts
.BinPath
);
998 Project project
= engine
.CreateNewProject ();
1000 TestMessageLogger testLogger
= new TestMessageLogger ();
1001 engine
.RegisterLogger (testLogger
);
1003 project
.LoadXml (projectString
);
1004 bool res
= project
.Build ("foo");
1006 testLogger
.DumpMessages ();
1007 Assert
.Fail ("A1: Build failed");
1010 CheckLoggedMessagesInOrder (testLogger
, new string [] {
1011 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1012 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1014 "TargetStarted", "List1: en_b.txt: en",
1015 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1017 "TargetStarted", "List1: gb_d.txt: gb",
1018 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
1020 CheckEngineEventCounts (testLogger
, 3, 3, 12, 12);
1024 public void TestTargetBatching3 ()
1026 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1028 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1029 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1030 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1031 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1033 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1034 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1036 <Foo Include=""1_a1""><Md>1</Md></Foo>
1037 <Foo Include=""2_b1""><Md>2</Md></Foo>
1038 <Foo Include=""1_c1""><Md>1</Md></Foo>
1040 <Target Name=""foo"" Inputs=""@(Foo)"" Outputs=""%(Md).foo"">
1041 <Message Text=""TargetStarted""/>
1042 <Message Text=""List1: @(List1): %(Culture)""/>
1043 <Message Text=""Foo: @(Foo): %(Md)""/>
1047 Engine engine
= new Engine (Consts
.BinPath
);
1048 Project project
= engine
.CreateNewProject ();
1050 TestMessageLogger testLogger
= new TestMessageLogger ();
1051 engine
.RegisterLogger (testLogger
);
1053 project
.LoadXml (projectString
);
1054 bool res
= project
.Build ("foo");
1056 testLogger
.DumpMessages ();
1057 Assert
.Fail ("A1: Build failed");
1060 CheckLoggedMessagesInOrder (testLogger
, new string [] {
1061 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1062 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
1063 "Foo: 1_a1;1_c1: 1",
1064 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1065 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
1068 CheckEngineEventCounts (testLogger
, 2, 2, 10, 10);
1072 public void TestTargetBatching4 ()
1074 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1076 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1077 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1078 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1079 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1081 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1082 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1084 <Foo Include=""1_a1""><Md>1</Md></Foo>
1085 <Foo Include=""2_b1""><Md>2</Md></Foo>
1086 <Foo Include=""1_c1""><Md>1</Md></Foo>
1088 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
1089 <Message Text=""TargetStarted""/>
1090 <Message Text=""List1: @(List1): %(Culture)""/>
1091 <Message Text=""List2: @(List2): %(Culture)""/>
1092 <Message Text=""Foo: @(Foo): %(Md)""/>
1096 Engine engine
= new Engine (Consts
.BinPath
);
1097 Project project
= engine
.CreateNewProject ();
1099 TestMessageLogger testLogger
= new TestMessageLogger ();
1100 engine
.RegisterLogger (testLogger
);
1102 project
.LoadXml (projectString
);
1103 bool res
= project
.Build ("foo");
1105 testLogger
.DumpMessages ();
1106 Assert
.Fail ("A1: Build failed");
1109 CheckLoggedMessagesInOrder (testLogger
, new string [] {
1110 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1111 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1112 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1114 "TargetStarted", "List1: en_b.txt: en",
1115 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1116 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1118 "TargetStarted", "List1: gb_d.txt: gb",
1119 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1120 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
1122 CheckEngineEventCounts (testLogger
, 3, 3, 18, 18);
1126 public void TestTargetBatching5 ()
1128 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1129 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
1130 <Message Text=""TargetStarted""/>
1134 Engine engine
= new Engine (Consts
.BinPath
);
1135 Project project
= engine
.CreateNewProject ();
1137 TestMessageLogger testLogger
= new TestMessageLogger ();
1138 engine
.RegisterLogger (testLogger
);
1140 project
.LoadXml (projectString
);
1141 bool res
= project
.Build ("foo");
1143 testLogger
.DumpMessages ();
1144 Assert
.Fail ("A1: Build failed");
1146 Assert
.AreEqual (1, testLogger
.CheckAny ("TargetStarted", MessageImportance
.Normal
),
1147 "A2: Target should've been skipped because of no inputs");
1148 CheckEngineEventCounts (testLogger
, 1, 1, 0, 0);
1152 public void TestTargetBatching6 ()
1154 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1156 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1157 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1158 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1159 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1161 <List3 Include=""fr_x.txt""><Culture>fr</Culture></List3>
1162 <List3 Include=""gb_z.txt""><Culture>gb</Culture></List3>
1164 <Foo Include=""1_a1""><Md>1</Md></Foo>
1165 <Foo Include=""2_b1""><Md>2</Md></Foo>
1166 <Foo Include=""1_c1""><Md>1</Md></Foo>
1169 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
1170 <Message Text=""TargetStarted"" />
1171 <Message Text=""List1: %(List1.Culture), List2: %(List2.Culture)"" />
1172 <Message Text=""List2: @(List2), Culture: %(Culture)"" />
1173 <Message Text=""List3: @(List3), Culture: %(Culture)"" />
1177 Engine engine
= new Engine (Consts
.BinPath
);
1178 Project project
= engine
.CreateNewProject ();
1180 TestMessageLogger testLogger
= new TestMessageLogger ();
1181 engine
.RegisterLogger (testLogger
);
1183 project
.LoadXml (projectString
);
1184 bool res
= project
.Build ("foo");
1186 testLogger
.DumpMessages ();
1187 Assert
.Fail ("A1: Build failed");
1190 CheckLoggedMessagesInOrder (testLogger
, new string [] {
1192 "List1: fr, List2: ",
1193 "List2: , Culture: ",
1194 "List3: fr_x.txt, Culture: fr",
1195 "List3: gb_z.txt, Culture: gb",
1198 "List1: en, List2: ",
1199 "List2: , Culture: ",
1200 "List3: fr_x.txt, Culture: fr",
1201 "List3: gb_z.txt, Culture: gb",
1204 "List1: gb, List2: ",
1205 "List2: , Culture: ",
1206 "List3: fr_x.txt, Culture: fr",
1207 "List3: gb_z.txt, Culture: gb"
1209 CheckEngineEventCounts (testLogger
, 3, 3, 15, 15);
1213 public void TestTargetBatching7 ()
1215 string projectString
= @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1217 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1218 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1219 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1220 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1222 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1223 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1225 <Foo Include=""1_a1""><Md>1</Md></Foo>
1226 <Foo Include=""2_b1""><Md>2</Md></Foo>
1227 <Foo Include=""1_c1""><Md>1</Md></Foo>
1230 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
1231 <Message Text=""TargetStarted"" />
1232 <Message Text=""List1: @(List1), List2: @(List2)""/>
1236 Engine engine
= new Engine (Consts
.BinPath
);
1237 Project project
= engine
.CreateNewProject ();
1239 TestMessageLogger testLogger
= new TestMessageLogger ();
1240 engine
.RegisterLogger (testLogger
);
1242 project
.LoadXml (projectString
);
1243 bool res
= project
.Build ("foo");
1245 testLogger
.DumpMessages ();
1246 Assert
.Fail ("A1: Build failed");
1249 CheckLoggedMessagesInOrder (testLogger
, new string [] {
1251 "List1: fr_a.txt;fr_c.txt, List2: fr_x.txt",
1254 "List1: en_b.txt, List2: ",
1257 "List1: gb_d.txt, List2: gb_z.txt"
1259 CheckEngineEventCounts (testLogger
, 3, 3, 6, 6);
1262 void CheckLoggedMessagesInOrder (TestMessageLogger logger
, string [] values
, string prefix
)
1265 for (int i
= 0; i
< values
.Length
; i
++) {
1266 logger
.CheckLoggedMessageHead (values
[i
], prefix
+ "#" + i
);
1268 if (logger
.NormalMessageCount
> 0)
1269 Assert
.Fail ("{0}: Expected {1} messages, but found {2}",
1270 prefix
, values
.Length
, values
.Length
+ logger
.NormalMessageCount
);
1271 } catch (NUnit
.Framework
.AssertionException
) {
1272 logger
.DumpMessages ();
1277 void CheckMessage (TestMessageLogger logger
, string culture
, string items
, string id
)
1279 logger
.CheckLoggedMessageHead (String
.Format ("Culture: {0} -- ResXFile: {1}", culture
, items
), id
);
1282 void CheckMessage2 (TestMessageLogger logger
, string culture
, string resx_files
, string nonresx_files
, string id
)
1284 logger
.CheckLoggedMessageHead (String
.Format ("Culture: {0} -- ResXFiles: {1} NonResXFiles: {2}", culture
, resx_files
, nonresx_files
), id
);
1287 void CheckLoggedMessageAny (TestMessageLogger logger
, string expected
, string id
)
1289 if (logger
.CheckAny (expected
, MessageImportance
.Normal
) == 1)
1290 Assert
.Fail ("{0}: Expected message '{1}' was not emitted.", id
, expected
);
1293 void CheckEngineEventCounts (TestMessageLogger logger
, int target_start
, int target_finish
, int task_start
, int task_finish
)
1295 Assert
.AreEqual (target_start
, logger
.TargetStarted
, "TargetStarted event count doesn't match");
1296 Assert
.AreEqual (target_finish
, logger
.TargetFinished
, "TargetFinished event count doesn't match");
1297 Assert
.AreEqual (task_start
, logger
.TaskStarted
, "TaskStarted event count doesn't match");
1298 Assert
.AreEqual (task_finish
, logger
.TaskFinished
, "TaskFinished event count doesn't match");