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
46 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
48 <ResXFile Include=""Item1"">
51 <ResXFile Include=""Item2"">
54 <ResXFile Include=""Item3"">
57 <ResXFile Include=""Item4"">
60 <ResXFile Include=""Item5"">
63 <ResXFile Include=""Item6"">
68 <Target Name=""ShowMessage"">
70 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
74 Engine engine = new Engine (Consts.BinPath);
75 Project project = engine.CreateNewProject ();
77 TestMessageLogger testLogger = new TestMessageLogger ();
78 engine.RegisterLogger (testLogger);
80 project.LoadXml (projectString);
81 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
83 CheckMessage (testLogger, "fr", "Item1;Item2;Item5", "A2");
84 CheckMessage (testLogger, "en", "Item3", "A3");
85 CheckMessage (testLogger, "gb", "Item4", "A4");
86 CheckMessage (testLogger, "it", "Item6", "A5");
88 CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
91 // Test1 with unqualified %(Culture)
95 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
97 <ResXFile Include=""Item1"">
100 <ResXFile Include=""Item2"">
101 <Culture>fr</Culture>
103 <ResXFile Include=""Item3"">
104 <Culture>en</Culture>
106 <ResXFile Include=""Item4"">
107 <Culture>gb</Culture>
109 <ResXFile Include=""Item5"">
110 <Culture>fr</Culture>
112 <ResXFile Include=""Item6"">
113 <Culture>it</Culture>
117 <Target Name=""ShowMessage"">
119 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
123 Engine engine = new Engine (Consts.BinPath);
124 Project project = engine.CreateNewProject ();
126 TestMessageLogger testLogger = new TestMessageLogger ();
127 engine.RegisterLogger (testLogger);
129 project.LoadXml (projectString);
130 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
132 CheckMessage (testLogger, "fr", "Item1;Item2;Item5", "A2");
133 CheckMessage (testLogger, "en", "Item3", "A3");
134 CheckMessage (testLogger, "gb", "Item4", "A4");
135 CheckMessage (testLogger, "it", "Item6", "A5");
137 CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
141 public void TestUnqualifiedMetadataReference ()
143 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
145 <ResXFile Include=""Item1"">
146 <Culture>fr</Culture>
148 <ResXFile Include=""Item5"" />
149 <ResXFile Include=""Item6"">
150 <Culture>it</Culture>
154 <Target Name=""ShowMessage"">
156 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
160 Engine engine = new Engine (Consts.BinPath);
161 Project project = engine.CreateNewProject ();
163 TestMessageLogger testLogger = new TestMessageLogger ();
164 engine.RegisterLogger (testLogger);
166 project.LoadXml (projectString);
168 //Fails as Culture is being referenced unqualified, and no Culture is
169 //specified for "Item5"
170 bool result = project.Build ("ShowMessage");
172 Assert.Fail ("A1: Build should have failed");
174 CheckEngineEventCounts (testLogger, 1, 1, 0, 0);
180 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
182 <ResXFile Include=""Item1"">
183 <Culture>fr</Culture>
185 <ResXFile Include=""Item5"" />
186 <ResXFile Include=""Item6"">
187 <Culture>it</Culture>
191 <Target Name=""ShowMessage"">
193 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
197 Engine engine = new Engine (Consts.BinPath);
198 Project project = engine.CreateNewProject ();
200 TestMessageLogger testLogger = new TestMessageLogger ();
201 engine.RegisterLogger (testLogger);
203 project.LoadXml (projectString);
205 //no Culture is specified for "Item5", but
206 //Culture is being referenced __qualified__, so works
207 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
209 CheckMessage (testLogger, "fr", "Item1", "A2");
210 CheckMessage (testLogger, "", "Item5", "A3");
211 CheckMessage (testLogger, "it", "Item6", "A3");
212 CheckEngineEventCounts (testLogger, 1, 1, 3, 3);
216 public void TestMultiItemCollections ()
218 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
220 <ResXFile Include=""Item1"">
221 <Culture>fr</Culture>
223 <ResXFile Include=""Item2"">
224 <Culture>fr</Culture>
226 <ResXFile Include=""Item3"">
227 <Culture>en</Culture>
229 <ResXFile Include=""Item4"">
230 <Culture>gb</Culture>
232 <ResXFile Include=""Item6"">
233 <Culture>it</Culture>
236 <NonResXFile Include=""Item7"">
237 <Culture>it</Culture>
239 <NonResXFile Include=""Item8"">
240 <Culture>en</Culture>
242 <NonResXFile Include=""Item9"">
243 <Culture>en</Culture>
247 <Target Name=""ShowMessage"">
249 Text = ""Culture: %(Culture) -- ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)"" />
253 Engine engine = new Engine (Consts.BinPath);
254 Project project = engine.CreateNewProject ();
256 TestMessageLogger testLogger = new TestMessageLogger ();
257 engine.RegisterLogger (testLogger);
259 project.LoadXml (projectString);
260 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
262 CheckMessage2 (testLogger, "fr", "Item1;Item2", string.Empty, "A2");
263 CheckMessage2 (testLogger, "en", "Item3", "Item8;Item9", "A3");
264 CheckMessage2 (testLogger, "gb", "Item4", string.Empty, "A4");
265 CheckMessage2 (testLogger, "it", "Item6", "Item7", "A6");
266 CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
270 public void TestConditionalBatching ()
272 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
274 <ResXFile Include=""Item1"">
275 <Culture>fr</Culture>
277 <ResXFile Include=""Item2"">
278 <Culture>fr</Culture>
280 <ResXFile Include=""Item3"">
281 <Culture>en</Culture>
283 <ResXFile Include=""Item4"">
284 <Culture>gb</Culture>
286 <ResXFile Include=""Item6"">
287 <Culture>it</Culture>
290 <NonResXFile Include=""Item7"">
291 <Culture>it</Culture>
293 <NonResXFile Include=""Item8"">
294 <Culture>en</Culture>
296 <NonResXFile Include=""Item9"">
297 <Culture>en</Culture>
301 <Target Name=""ShowMessage"">
303 Text = ""ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)""
304 Condition = ""'%(Culture)' == 'fr'""/>
308 Engine engine = new Engine (Consts.BinPath);
309 Project project = engine.CreateNewProject ();
311 TestMessageLogger testLogger = new TestMessageLogger ();
312 engine.RegisterLogger (testLogger);
314 project.LoadXml (projectString);
315 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
317 testLogger.CheckLoggedMessageHead ("ResXFiles: Item1;Item2 NonResXFiles: ", "A2");
318 CheckEngineEventCounts (testLogger, 1, 1, 1, 1);
322 public void TestMultipleMetadataReference ()
324 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
326 <ExampColl Include=""Item1"">
329 <ExampColl Include=""Item2"">
332 <ExampColl Include=""Item3"">
336 <ExampColl2 Include=""Item4"">
339 <ExampColl2 Include=""Item5"">
343 <ExampColl2 Include=""Item6"">
348 <Target Name=""ShowMessage"">
349 <Message Text = ""Number: %(Number) Color: %(ExampColl2.Color)-- Items in ExampColl: @(ExampColl) ExampColl2: @(ExampColl2)""/>
353 Engine engine = new Engine (Consts.BinPath);
354 Project project = engine.CreateNewProject ();
356 TestMessageLogger testLogger = new TestMessageLogger ();
357 engine.RegisterLogger (testLogger);
359 project.LoadXml (projectString);
360 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
362 CheckLoggedMessageAny (testLogger, "Number: 1 Color: -- Items in ExampColl: Item1;Item3 ExampColl2: Item4", "A2");
363 CheckLoggedMessageAny (testLogger, "Number: 2 Color: Red-- Items in ExampColl: ExampColl2: Item5", "A3");
364 CheckLoggedMessageAny (testLogger, "Number: 3 Color: Green-- Items in ExampColl: ExampColl2: Item6", "A4");
365 CheckLoggedMessageAny (testLogger, "Number: 2 Color: -- Items in ExampColl: Item2 ExampColl2: ", "A5");
366 Assert.AreEqual (0, testLogger.Count, "A6");
367 CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
371 public void TestMultipleMetadataReference2 ()
373 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
375 <GroupA Include=""file1.txt""/>
376 <GroupA Include=""file2.txt""/>
377 <GroupA Include=""file3.txt""/>
378 <GroupA Include=""file3.txt""/>
379 <GroupA Include=""file4.txt""/>
383 <GroupB Include=""file1.txt""/>
384 <GroupB Include=""file3.txt""/>
385 <GroupB Include=""file5.txt""/>
387 <GroupC Include=""PreExistingValue""/>
390 <Target Name=""Build"">
391 <CreateItem Include=""@(GroupA)"" Condition=""'%(Identity)' != '' and '@(GroupA)' != '' and '@(GroupB)' != ''"" >
392 <Output TaskParameter=""Include"" ItemName=""GroupC""/>
394 <Message Text=""%(GroupC.Identity)""/>
398 Engine engine = new Engine (Consts.BinPath);
399 Project project = engine.CreateNewProject ();
401 TestMessageLogger testLogger = new TestMessageLogger ();
402 engine.RegisterLogger (testLogger);
404 project.LoadXml (projectString);
405 Assert.IsTrue (project.Build ("Build"), "A1: Build failed");
407 BuildItemGroup include = project.GetEvaluatedItemsByName ("GroupC");
408 Assert.AreEqual (4, include.Count, "A2");
410 string [,] additional_metadata = new string [,] { { "Identity", "PreExistingValue" } };
411 CreateItemTest.CheckBuildItem (include [0], "GroupC", additional_metadata, "PreExistingValue", "A3");
413 additional_metadata = new string [,] { { "Identity", "file1.txt" } };
414 CreateItemTest.CheckBuildItem (include [1], "GroupC", additional_metadata, "file1.txt", "A4");
416 additional_metadata = new string [,] { { "Identity", "file3.txt" } };
417 CreateItemTest.CheckBuildItem (include [2], "GroupC", additional_metadata, "file3.txt", "A5");
418 CreateItemTest.CheckBuildItem (include [3], "GroupC", additional_metadata, "file3.txt", "A6");
420 CheckEngineEventCounts (testLogger, 1, 1, 5, 5);
424 public void TestIdentity ()
426 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
428 <ExampColl Include=""Item1""/>
429 <ExampColl Include=""Item2""/>
430 <ExampColl Include=""Item3""/>
431 <ExampColl Include=""Item4""/>
432 <ExampColl Include=""Item4""/>
433 <ExampColl Include=""Item5""/>
434 <ExampColl Include=""Item6""/>
436 <Target Name=""ShowMessage"">
437 <Message Text = ""Identity: %(IdenTIty) -- Items in ExampColl: @(ExampColl)""/>
441 Engine engine = new Engine (Consts.BinPath);
442 Project project = engine.CreateNewProject ();
444 TestMessageLogger testLogger = new TestMessageLogger ();
445 engine.RegisterLogger (testLogger);
447 project.LoadXml (projectString);
448 Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
450 CheckLoggedMessageAny (testLogger, "Identity: Item1 -- Items in ExampColl: Item1", "A2");
451 CheckLoggedMessageAny (testLogger, "Identity: Item2 -- Items in ExampColl: Item2", "A3");
452 CheckLoggedMessageAny (testLogger, "Identity: Item3 -- Items in ExampColl: Item3", "A4");
453 CheckLoggedMessageAny (testLogger, "Identity: Item4 -- Items in ExampColl: Item4;Item4", "A5");
454 CheckLoggedMessageAny (testLogger, "Identity: Item5 -- Items in ExampColl: Item5", "A6");
455 CheckLoggedMessageAny (testLogger, "Identity: Item6 -- Items in ExampColl: Item6", "A7");
456 Assert.AreEqual (0, testLogger.Count, "A8");
457 CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
461 public void TestFilter ()
463 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
465 <fruit Include=""apple"">
466 <consistency>firm</consistency>
468 <fruit Include=""orange"">
469 <consistency>pulpy</consistency>
471 <fruit Include=""banana"">
472 <consistency>softish</consistency>
474 <fruit Include=""pear"">
475 <consistency>unsound</consistency>
477 <fruit Include=""apricot"">
478 <consistency>unsound</consistency>
481 <Target Name=""Compost"">
482 <CreateItem Include=""@(fruit)"" Condition=""'%(consistency)' == 'pulpy' or '%(consistency)' == 'unsound' "">
483 <Output TaskParameter=""Include"" ItemName=""Final""/>
488 Engine engine = new Engine (Consts.BinPath);
489 Project project = engine.CreateNewProject ();
491 TestMessageLogger testLogger = new TestMessageLogger ();
492 engine.RegisterLogger (testLogger);
494 project.LoadXml (projectString);
495 Assert.IsTrue (project.Build ("Compost"), "A1: Build failed");
497 BuildItemGroup include = project.GetEvaluatedItemsByName ("Final");
498 Assert.AreEqual (3, include.Count, "A2");
500 string [,] additional_metadata = new string [,] { { "Identity", "orange" } };
501 CreateItemTest.CheckBuildItem (include [0], "Final", additional_metadata, "orange", "A3");
503 additional_metadata = new string [,] { { "Identity", "pear" } };
504 CreateItemTest.CheckBuildItem (include [1], "Final", additional_metadata, "pear", "A4");
506 additional_metadata = new string [,] { { "Identity", "apricot" } };
507 CreateItemTest.CheckBuildItem (include [2], "Final", additional_metadata, "apricot", "A5");
508 CheckEngineEventCounts (testLogger, 1, 1, 2, 2);
512 // test for metadata refs in properties or items
513 public void TestNoBatching () {
514 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
516 <item3 Include=""foo""/>
517 <item2 Include=""%(item3.Identity)""/>
518 <item0 Include=""@(item3)""/>
521 <Prop1>%(item0.Identity)</Prop1>
524 <Message Text=""Prop1: $(Prop1)""/>
525 <Message Text=""Item2: @(item2)""/>
529 Engine engine = new Engine (Consts.BinPath);
530 Project project = engine.CreateNewProject ();
532 TestMessageLogger testLogger = new TestMessageLogger ();
533 engine.RegisterLogger (testLogger);
535 project.LoadXml (projectString);
536 if (!project.Build ("1")) {
537 testLogger.DumpMessages ();
538 Assert.Fail ("Build failed");
541 testLogger.CheckLoggedMessageHead ("Prop1: %(item0.Identity)", "A1");
542 testLogger.CheckLoggedMessageHead ("Item2: %(item3.Identity)", "A2");
543 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
547 // test for metadata refs via metadata refs
548 // batching should happen only on basis of the task attributes,
549 // and not the resolved expression values
550 public void TestBatching1 () {
551 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
553 <item3 Include=""foo""/>
554 <item2 Include=""%(item3.Identity)""/>
556 <item4 Include=""%(item2.Identity);@(item3);@(nonexistant)""/>
557 <item4 Include=""bar""/>
560 <Message Text=""Item4: %(item4.Identity)""/>
564 Engine engine = new Engine (Consts.BinPath);
565 Project project = engine.CreateNewProject ();
567 TestMessageLogger testLogger = new TestMessageLogger ();
568 engine.RegisterLogger (testLogger);
570 project.LoadXml (projectString);
571 if (!project.Build ("1")) {
572 testLogger.DumpMessages ();
573 Assert.Fail ("Build failed");
576 testLogger.CheckLoggedMessageHead ("Item4: %(item2.Identity)", "A1");
577 testLogger.CheckLoggedMessageHead ("Item4: foo", "A2");
578 testLogger.CheckLoggedMessageHead ("Item4: bar", "A3");
579 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
583 // test for metadata refs via metadata refs
584 // batching should happen only on basis of the task attributes,
585 // and not the resolved expression values
586 public void TestConditionalBatching2 () {
587 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
589 <item2 Include=""%(item3.Identity)""/>
590 <item4 Include=""%(item2.Identity);@(item3)""/>
593 <Message Text=""Item3: %(item2.Identity)"" Condition="" '%(item5.Identity)' == '' ""/>
594 <Message Text=""Item4: %(item4.Identity)""/>
598 Engine engine = new Engine (Consts.BinPath);
599 Project project = engine.CreateNewProject ();
601 TestMessageLogger testLogger = new TestMessageLogger ();
602 engine.RegisterLogger (testLogger);
604 project.LoadXml (projectString);
605 if (!project.Build ("1")) {
606 testLogger.DumpMessages ();
607 Assert.Fail ("Build failed");
610 testLogger.CheckLoggedMessageHead ("Item3: %(item3.Identity)", "A1");
611 testLogger.CheckLoggedMessageHead ("Item4: %(item2.Identity)", "A2");
612 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
616 public void TestBatchingWithUnbatchedItems () {
617 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
619 <Item1 Include=""One""/>
620 <Item1 Include=""Two""/>
625 <Message Text=""Item1: %(Item1.Identity) | B: @(B)""/>
629 Engine engine = new Engine (Consts.BinPath);
630 Project project = engine.CreateNewProject ();
632 TestMessageLogger testLogger = new TestMessageLogger ();
633 engine.RegisterLogger (testLogger);
635 project.LoadXml (projectString);
636 if (!project.Build ("1")) {
637 testLogger.DumpMessages ();
638 Assert.Fail ("Build failed");
642 testLogger.CheckLoggedMessageHead ("Item1: One | B: abc", "A1");
643 testLogger.CheckLoggedMessageHead ("Item1: Two | B: abc", "A2");
645 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
646 } catch (AssertionException) {
647 testLogger.DumpMessages ();
653 public void TestPropertiesWithBatchedReferences () {
654 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
656 <Item1 Include=""One""/>
657 <Item1 Include=""Two""/>
659 <Item1Ref Include=""@(Item1)""/>
662 <Prop1>@(Item1)</Prop1>
663 <Prop2>@(Item1Ref)</Prop2>
666 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
670 Engine engine = new Engine (Consts.BinPath);
671 Project project = engine.CreateNewProject ();
673 TestMessageLogger testLogger = new TestMessageLogger ();
674 engine.RegisterLogger (testLogger);
676 project.LoadXml (projectString);
677 if (!project.Build ("1")) {
679 testLogger.DumpMessages ();
680 Assert.Fail ("Build failed");
684 testLogger.CheckLoggedMessageHead ("Item1: One | Prop1: One | Prop2: One;Two", "A1");
685 testLogger.CheckLoggedMessageHead ("Item1: Two | Prop1: Two | Prop2: One;Two", "A2");
687 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
688 } catch (AssertionException) {
689 testLogger.DumpMessages ();
695 public void TestPropertiesWithDynamicItems () {
696 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
698 <Item1 Include=""One""/>
699 <Item1 Include=""Two""/>
701 <Item2 Include=""Z""/>
702 <Item2Ref Include=""@(Item2)"" />
705 <Prop1>@(Item2)</Prop1>
706 <Prop2>@(Item2Ref)</Prop2>
709 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
710 <Message Text=""Item2: @(Item2) | Item2Ref: @(Item2Ref)""/>
711 <CreateItem Include=""A;B"">
712 <Output TaskParameter=""Include"" ItemName=""Item2""/>
714 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
715 <Message Text=""Item2: @(Item2) | Item2Ref: @(Item2Ref)""/>
719 Engine engine = new Engine (Consts.BinPath);
720 Project project = engine.CreateNewProject ();
722 TestMessageLogger testLogger = new TestMessageLogger ();
723 engine.RegisterLogger (testLogger);
725 project.LoadXml (projectString);
726 if (!project.Build ("1")) {
728 testLogger.DumpMessages ();
729 Assert.Fail ("Build failed");
734 testLogger.CheckLoggedMessageHead ("Item1: One | Prop1: Z | Prop2: Z", "A1");
735 testLogger.CheckLoggedMessageHead ("Item1: Two | Prop1: Z | Prop2: Z", "A2");
736 testLogger.CheckLoggedMessageHead ("Item2: Z | Item2Ref: Z", "A3");
738 testLogger.CheckLoggedMessageHead ("Item1: One | Prop1: Z;A;B | Prop2: Z", "A4");
739 testLogger.CheckLoggedMessageHead ("Item1: Two | Prop1: Z;A;B | Prop2: Z", "A5");
740 testLogger.CheckLoggedMessageHead ("Item2: Z;A;B | Item2Ref: Z", "A3");
742 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
743 } catch (AssertionException) {
744 testLogger.DumpMessages ();
750 public void TestTargetInvocationFromBatchedTask () {
751 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
753 <Item1 Include=""One""/>
754 <Item1 Include=""Two""/>
756 <Item1Ref Include=""@(Item1)"" />
759 <Prop1>@(Item1)</Prop1>
760 <Prop2>@(Item1Ref)</Prop2>
763 <CallTarget Targets='foo' Condition="" '%(Item1.Identity)' != ''"" />
764 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
765 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
768 <Message Text=""(foo) Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
769 <Message Text=""(foo) Prop1: $(Prop1) Prop2: $(Prop2)""/>
773 Engine engine = new Engine (Consts.BinPath);
774 Project project = engine.CreateNewProject ();
776 TestMessageLogger testLogger = new TestMessageLogger ();
777 engine.RegisterLogger (testLogger);
779 project.LoadXml (projectString);
780 if (!project.Build ("1")) {
782 testLogger.DumpMessages ();
783 Assert.Fail ("Build failed");
787 testLogger.CheckLoggedMessageHead ("(foo) Item1: One;Two Item1Ref: One;Two", "A1");
788 testLogger.CheckLoggedMessageHead ("(foo) Prop1: One;Two Prop2: One;Two", "A2");
790 testLogger.CheckLoggedMessageHead ("Item1: One;Two Item1Ref: One;Two", "A3");
791 testLogger.CheckLoggedMessageHead ("Prop1: One;Two Prop2: One;Two", "A4");
793 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
794 } catch (AssertionException) {
795 testLogger.DumpMessages ();
801 public void TestTargetInvocationFromBatchedTarget () {
802 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
804 <Item1 Include=""One""/>
805 <Item1 Include=""Two""/>
807 <Item1Ref Include=""@(Item1)"" />
810 <Prop1>@(Item1)</Prop1>
811 <Prop2>@(Item1Ref)</Prop2>
813 <Target Name='1' Inputs=""%(Item1.Identity)"" Outputs=""Nonexistant.foobar"">
814 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
815 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
817 <CallTarget Targets='foo' />
819 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
820 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
822 <Target Name='foo' Condition="" '@(Item1)' != 'One' "">
823 <Message Text=""(foo) Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
824 <Message Text=""(foo) Prop1: $(Prop1) Prop2: $(Prop2)""/>
828 Engine engine = new Engine (Consts.BinPath);
829 Project project = engine.CreateNewProject ();
831 TestMessageLogger testLogger = new TestMessageLogger ();
832 engine.RegisterLogger (testLogger);
834 project.LoadXml (projectString);
835 if (!project.Build ("1")) {
837 testLogger.DumpMessages ();
838 Assert.Fail ("Build failed");
842 testLogger.CheckLoggedMessageHead ("Item1: One Item1Ref: One;Two", "A1");
843 testLogger.CheckLoggedMessageHead ("Prop1: One Prop2: One;Two", "A2");
845 testLogger.CheckLoggedMessageHead ("(foo) Item1: One;Two Item1Ref: One;Two", "A3");
846 testLogger.CheckLoggedMessageHead ("(foo) Prop1: One;Two Prop2: One;Two", "A4");
848 testLogger.CheckLoggedMessageHead ("Item1: One Item1Ref: One;Two", "A5");
849 testLogger.CheckLoggedMessageHead ("Prop1: One Prop2: One;Two", "A6");
851 //second batch, foo has already run, so doesn't execute again
852 testLogger.CheckLoggedMessageHead ("Item1: Two Item1Ref: One;Two", "A7");
853 testLogger.CheckLoggedMessageHead ("Prop1: Two Prop2: One;Two", "A8");
855 testLogger.CheckLoggedMessageHead ("Item1: Two Item1Ref: One;Two", "A9");
856 testLogger.CheckLoggedMessageHead ("Prop1: Two Prop2: One;Two", "A10");
858 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
859 } catch (AssertionException) {
860 testLogger.DumpMessages ();
866 public void TestBatchingWithUnqualifiedMetadataReference () {
867 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
869 <Item1 Include=""One""><Md>1</Md></Item1>
870 <Item1 Include=""Two""><Md>2</Md></Item1>
871 <Item1Ref Include=""@(Item1)"" />
873 <Item2 Include=""Three""><Md>3</Md></Item2>
874 <Item2 Include=""Four""><Md>4</Md></Item2>
875 <Item2Ref Include=""@(Item2)"" />
878 <Prop1>@(Item1)</Prop1>
879 <Prop1Ref>@(Item1Ref)</Prop1Ref>
881 <Prop2>@(Item2)</Prop2>
882 <Prop2Ref>@(Item2Ref)</Prop2Ref>
885 <Message Text=""For md: %(Md) Item1: @(Item1) Item1Ref: @(Item1Ref) Item2: @(Item2) Item2Ref: @(Item2Ref) " +
886 @" Prop1: $(Prop1) Prop1Ref: $(Prop1Ref) Prop2: $(Prop2) Prop2Ref: $(Prop2Ref)""/>
890 Engine engine = new Engine (Consts.BinPath);
891 Project project = engine.CreateNewProject ();
893 TestMessageLogger testLogger = new TestMessageLogger ();
894 engine.RegisterLogger (testLogger);
896 project.LoadXml (projectString);
897 if (!project.Build ("1")) {
899 testLogger.DumpMessages ();
900 Assert.Fail ("Build failed");
902 testLogger.DumpMessages ();
905 testLogger.CheckLoggedAny ("For md: 3 Item1: Item1Ref: Item2: Three Item2Ref: Three Prop1: Prop1Ref: Prop2: Three Prop2Ref: Three", MessageImportance.Normal, "A1");
906 testLogger.CheckLoggedAny ("For md: 4 Item1: Item1Ref: Item2: Four Item2Ref: Four Prop1: Prop1Ref: Prop2: Four Prop2Ref: Four", MessageImportance.Normal, "A2");
907 testLogger.CheckLoggedAny ("For md: 1 Item1: One Item1Ref: One Item2: Item2Ref: Prop1: One Prop1Ref: One Prop2: Prop2Ref: ", MessageImportance.Normal, "A3");
908 testLogger.CheckLoggedAny ("For md: 2 Item1: Two Item1Ref: Two Item2: Item2Ref: Prop1: Two Prop1Ref: Two Prop2: Prop2Ref: ", MessageImportance.Normal, "A4");
910 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
911 } catch (AssertionException) {
912 testLogger.DumpMessages ();
921 public void TestTargetBatching1 ()
923 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
925 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
926 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
927 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
928 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
930 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
931 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
933 <Foo Include=""1_a1""><Md>1</Md></Foo>
934 <Foo Include=""2_b1""><Md>2</Md></Foo>
935 <Foo Include=""1_c1""><Md>1</Md></Foo>
938 <Target Name=""foo"" >
939 <Message Text=""TargetStarted""/>
940 <Message Text=""List1: @(List1): %(Culture)""/>
941 <Message Text=""Foo: @(Foo): %(Md)""/>
945 Engine engine = new Engine (Consts.BinPath);
946 Project project = engine.CreateNewProject ();
948 TestMessageLogger testLogger = new TestMessageLogger ();
949 engine.RegisterLogger (testLogger);
951 project.LoadXml (projectString);
952 bool res = project.Build ("foo");
954 testLogger.DumpMessages ();
955 Assert.Fail ("A1: Build failed");
958 CheckLoggedMessagesInOrder (testLogger, new string [] {
959 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
960 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
961 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
963 CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
967 public void TestTargetBatching2 ()
969 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
971 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
972 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
973 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
974 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
976 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
977 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
979 <Foo Include=""1_a1""><Md>1</Md></Foo>
980 <Foo Include=""2_b1""><Md>2</Md></Foo>
981 <Foo Include=""1_c1""><Md>1</Md></Foo>
984 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
985 <Message Text=""TargetStarted""/>
986 <Message Text=""List1: @(List1): %(Culture)""/>
987 <Message Text=""Foo: @(Foo): %(Md)""/>
991 Engine engine = new Engine (Consts.BinPath);
992 Project project = engine.CreateNewProject ();
994 TestMessageLogger testLogger = new TestMessageLogger ();
995 engine.RegisterLogger (testLogger);
997 project.LoadXml (projectString);
998 bool res = project.Build ("foo");
1000 testLogger.DumpMessages ();
1001 Assert.Fail ("A1: Build failed");
1004 CheckLoggedMessagesInOrder (testLogger, new string [] {
1005 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1006 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1008 "TargetStarted", "List1: en_b.txt: en",
1009 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1011 "TargetStarted", "List1: gb_d.txt: gb",
1012 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
1014 CheckEngineEventCounts (testLogger, 3, 3, 12, 12);
1018 public void TestTargetBatching3 ()
1020 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1022 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1023 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1024 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1025 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1027 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1028 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1030 <Foo Include=""1_a1""><Md>1</Md></Foo>
1031 <Foo Include=""2_b1""><Md>2</Md></Foo>
1032 <Foo Include=""1_c1""><Md>1</Md></Foo>
1034 <Target Name=""foo"" Inputs=""@(Foo)"" Outputs=""%(Md).foo"">
1035 <Message Text=""TargetStarted""/>
1036 <Message Text=""List1: @(List1): %(Culture)""/>
1037 <Message Text=""Foo: @(Foo): %(Md)""/>
1041 Engine engine = new Engine (Consts.BinPath);
1042 Project project = engine.CreateNewProject ();
1044 TestMessageLogger testLogger = new TestMessageLogger ();
1045 engine.RegisterLogger (testLogger);
1047 project.LoadXml (projectString);
1048 bool res = project.Build ("foo");
1050 testLogger.DumpMessages ();
1051 Assert.Fail ("A1: Build failed");
1054 CheckLoggedMessagesInOrder (testLogger, new string [] {
1055 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1056 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
1057 "Foo: 1_a1;1_c1: 1",
1058 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1059 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
1062 CheckEngineEventCounts (testLogger, 2, 2, 10, 10);
1066 public void TestTargetBatching4 ()
1068 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1070 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1071 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1072 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1073 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1075 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1076 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1078 <Foo Include=""1_a1""><Md>1</Md></Foo>
1079 <Foo Include=""2_b1""><Md>2</Md></Foo>
1080 <Foo Include=""1_c1""><Md>1</Md></Foo>
1082 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
1083 <Message Text=""TargetStarted""/>
1084 <Message Text=""List1: @(List1): %(Culture)""/>
1085 <Message Text=""List2: @(List2): %(Culture)""/>
1086 <Message Text=""Foo: @(Foo): %(Md)""/>
1090 Engine engine = new Engine (Consts.BinPath);
1091 Project project = engine.CreateNewProject ();
1093 TestMessageLogger testLogger = new TestMessageLogger ();
1094 engine.RegisterLogger (testLogger);
1096 project.LoadXml (projectString);
1097 bool res = project.Build ("foo");
1099 testLogger.DumpMessages ();
1100 Assert.Fail ("A1: Build failed");
1103 CheckLoggedMessagesInOrder (testLogger, new string [] {
1104 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1105 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1106 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1108 "TargetStarted", "List1: en_b.txt: en",
1109 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1110 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1112 "TargetStarted", "List1: gb_d.txt: gb",
1113 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1114 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
1116 CheckEngineEventCounts (testLogger, 3, 3, 18, 18);
1120 public void TestTargetBatching5 ()
1122 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1123 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
1124 <Message Text=""TargetStarted""/>
1128 Engine engine = new Engine (Consts.BinPath);
1129 Project project = engine.CreateNewProject ();
1131 TestMessageLogger testLogger = new TestMessageLogger ();
1132 engine.RegisterLogger (testLogger);
1134 project.LoadXml (projectString);
1135 bool res = project.Build ("foo");
1137 testLogger.DumpMessages ();
1138 Assert.Fail ("A1: Build failed");
1140 Assert.AreEqual (1, testLogger.CheckAny ("TargetStarted", MessageImportance.Normal),
1141 "A2: Target should've been skipped because of no inputs");
1142 CheckEngineEventCounts (testLogger, 1, 1, 0, 0);
1146 public void TestTargetBatching6 ()
1148 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1150 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1151 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1152 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1153 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1155 <List3 Include=""fr_x.txt""><Culture>fr</Culture></List3>
1156 <List3 Include=""gb_z.txt""><Culture>gb</Culture></List3>
1158 <Foo Include=""1_a1""><Md>1</Md></Foo>
1159 <Foo Include=""2_b1""><Md>2</Md></Foo>
1160 <Foo Include=""1_c1""><Md>1</Md></Foo>
1163 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
1164 <Message Text=""TargetStarted"" />
1165 <Message Text=""List1: %(List1.Culture), List2: %(List2.Culture)"" />
1166 <Message Text=""List2: @(List2), Culture: %(Culture)"" />
1167 <Message Text=""List3: @(List3), Culture: %(Culture)"" />
1171 Engine engine = new Engine (Consts.BinPath);
1172 Project project = engine.CreateNewProject ();
1174 TestMessageLogger testLogger = new TestMessageLogger ();
1175 engine.RegisterLogger (testLogger);
1177 project.LoadXml (projectString);
1178 bool res = project.Build ("foo");
1180 testLogger.DumpMessages ();
1181 Assert.Fail ("A1: Build failed");
1184 CheckLoggedMessagesInOrder (testLogger, new string [] {
1186 "List1: fr, List2: ",
1187 "List2: , Culture: ",
1188 "List3: fr_x.txt, Culture: fr",
1189 "List3: gb_z.txt, Culture: gb",
1192 "List1: en, List2: ",
1193 "List2: , Culture: ",
1194 "List3: fr_x.txt, Culture: fr",
1195 "List3: gb_z.txt, Culture: gb",
1198 "List1: gb, List2: ",
1199 "List2: , Culture: ",
1200 "List3: fr_x.txt, Culture: fr",
1201 "List3: gb_z.txt, Culture: gb"
1203 CheckEngineEventCounts (testLogger, 3, 3, 15, 15);
1207 public void TestTargetBatching7 ()
1209 string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1211 <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1212 <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1213 <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1214 <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1216 <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1217 <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1219 <Foo Include=""1_a1""><Md>1</Md></Foo>
1220 <Foo Include=""2_b1""><Md>2</Md></Foo>
1221 <Foo Include=""1_c1""><Md>1</Md></Foo>
1224 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
1225 <Message Text=""TargetStarted"" />
1226 <Message Text=""List1: @(List1), List2: @(List2)""/>
1230 Engine engine = new Engine (Consts.BinPath);
1231 Project project = engine.CreateNewProject ();
1233 TestMessageLogger testLogger = new TestMessageLogger ();
1234 engine.RegisterLogger (testLogger);
1236 project.LoadXml (projectString);
1237 bool res = project.Build ("foo");
1239 testLogger.DumpMessages ();
1240 Assert.Fail ("A1: Build failed");
1243 CheckLoggedMessagesInOrder (testLogger, new string [] {
1245 "List1: fr_a.txt;fr_c.txt, List2: fr_x.txt",
1248 "List1: en_b.txt, List2: ",
1251 "List1: gb_d.txt, List2: gb_z.txt"
1253 CheckEngineEventCounts (testLogger, 3, 3, 6, 6);
1256 void CheckLoggedMessagesInOrder (TestMessageLogger logger, string [] values, string prefix)
1259 for (int i = 0; i < values.Length; i++) {
1260 logger.CheckLoggedMessageHead (values [i], prefix + "#" + i);
1262 if (logger.NormalMessageCount > 0)
1263 Assert.Fail ("{0}: Expected {1} messages, but found {2}",
1264 prefix, values.Length, values.Length + logger.NormalMessageCount);
1265 } catch (NUnit.Framework.AssertionException) {
1266 logger.DumpMessages ();
1271 void CheckMessage (TestMessageLogger logger, string culture, string items, string id)
1273 logger.CheckLoggedMessageHead (String.Format ("Culture: {0} -- ResXFile: {1}", culture, items), id);
1276 void CheckMessage2 (TestMessageLogger logger, string culture, string resx_files, string nonresx_files, string id)
1278 logger.CheckLoggedMessageHead (String.Format ("Culture: {0} -- ResXFiles: {1} NonResXFiles: {2}", culture, resx_files, nonresx_files), id);
1281 void CheckLoggedMessageAny (TestMessageLogger logger, string expected, string id)
1283 if (logger.CheckAny (expected, MessageImportance.Normal) == 1)
1284 Assert.Fail ("{0}: Expected message '{1}' was not emitted.", id, expected);
1287 void CheckEngineEventCounts (TestMessageLogger logger, int target_start, int target_finish, int task_start, int task_finish)
1289 Assert.AreEqual (target_start, logger.TargetStarted, "TargetStarted event count doesn't match");
1290 Assert.AreEqual (target_finish, logger.TargetFinished, "TargetFinished event count doesn't match");
1291 Assert.AreEqual (task_start, logger.TaskStarted, "TaskStarted event count doesn't match");
1292 Assert.AreEqual (task_finish, logger.TaskFinished, "TaskFinished event count doesn't match");