Merge pull request #817 from desdesdes/master
[mono.git] / mcs / class / Microsoft.Build.Tasks / Test / Microsoft.Build.Tasks / TaskBatchingTest.cs
1 //
2 // TaskBatchingTest.cs
3 //
4 // Author:
5 //   Ankit Jain (jankit@novell.com)
6 //
7 // Copyright 2008 Novell, Inc (http://www.novell.com)
8 // Copyright 2009 Novell, Inc (http://www.novell.com)
9 //
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:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
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.
28
29 using System;
30 using System.Collections.Generic;
31 using System.Text;
32 using NUnit.Framework;
33 using Microsoft.Build.BuildEngine;
34 using Microsoft.Build.Framework;
35 using Microsoft.Build.Tasks;
36 using Microsoft.Build.Utilities;
37
38 namespace MonoTests.Microsoft.Build.Tasks
39 {
40         [TestFixture]
41         public class TaskBatchingTest
42         {
43                 string projectHeader;
44                 public TaskBatchingTest ()
45                 {
46                         projectHeader = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" " + Consts.ToolsVersionString + ">";
47                 }
48
49                 [Test]
50                 public void Test1 ()
51                 {
52                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
53                                 <ItemGroup>
54                                         <ResXFile Include=""Item1"">
55                                                 <Culture>fr</Culture>
56                                         </ResXFile>
57                                         <ResXFile Include=""Item2"">
58                                                 <Culture>fr</Culture>
59                                         </ResXFile>
60                                         <ResXFile Include=""Item3"">
61                                                 <Culture>en</Culture>
62                                         </ResXFile>
63                                         <ResXFile Include=""Item4"">
64                                                 <Culture>gb</Culture>
65                                         </ResXFile>
66                                         <ResXFile Include=""Item5"">
67                                                 <Culture>fr</Culture>
68                                         </ResXFile>
69                                         <ResXFile Include=""Item6"">
70                                                 <Culture>it</Culture>
71                                         </ResXFile>
72                                 </ItemGroup>
73
74                                 <Target Name=""ShowMessage"">
75                                         <Message
76                                                 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
77                                 </Target>
78                           </Project>";
79
80                         Engine engine = new Engine (Consts.BinPath);
81                         Project project = engine.CreateNewProject ();
82
83                         TestMessageLogger testLogger = new TestMessageLogger ();
84                         engine.RegisterLogger (testLogger);
85
86                         project.LoadXml (projectString);
87                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
88
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");
93
94                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
95                 }
96
97                 // Test1 with unqualified %(Culture)
98                 [Test]
99                 public void Test2 ()
100                 {
101                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
102                                 <ItemGroup>
103                                         <ResXFile Include=""Item1"">
104                                                 <Culture>fr</Culture>
105                                         </ResXFile>
106                                         <ResXFile Include=""Item2"">
107                                                 <Culture>fr</Culture>
108                                         </ResXFile>
109                                         <ResXFile Include=""Item3"">
110                                                 <Culture>en</Culture>
111                                         </ResXFile>
112                                         <ResXFile Include=""Item4"">
113                                                 <Culture>gb</Culture>
114                                         </ResXFile>
115                                         <ResXFile Include=""Item5"">
116                                                 <Culture>fr</Culture>
117                                         </ResXFile>
118                                         <ResXFile Include=""Item6"">
119                                                 <Culture>it</Culture>
120                                         </ResXFile>
121                                 </ItemGroup>
122
123                                 <Target Name=""ShowMessage"">
124                                         <Message
125                                                 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
126                                 </Target>
127                           </Project>";
128
129                         Engine engine = new Engine (Consts.BinPath);
130                         Project project = engine.CreateNewProject ();
131
132                         TestMessageLogger testLogger = new TestMessageLogger ();
133                         engine.RegisterLogger (testLogger);
134
135                         project.LoadXml (projectString);
136                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
137
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");
142
143                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
144                 }
145
146                 [Test]
147                 public void TestUnqualifiedMetadataReference ()
148                 {
149                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
150                                 <ItemGroup>
151                                         <ResXFile Include=""Item1"">
152                                                 <Culture>fr</Culture>
153                                         </ResXFile>
154                                         <ResXFile Include=""Item5"" />
155                                         <ResXFile Include=""Item6"">
156                                                 <Culture>it</Culture>
157                                         </ResXFile>
158                                 </ItemGroup>
159
160                                 <Target Name=""ShowMessage"">
161                                         <Message
162                                                 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
163                                 </Target>
164                           </Project>";
165
166                         Engine engine = new Engine (Consts.BinPath);
167                         Project project = engine.CreateNewProject ();
168
169                         TestMessageLogger testLogger = new TestMessageLogger ();
170                         engine.RegisterLogger (testLogger);
171
172                         project.LoadXml (projectString);
173
174                         //Fails as Culture is being referenced unqualified, and no Culture is
175                         //specified for "Item5"
176                         bool result = project.Build ("ShowMessage");
177                         if (result)
178                                 Assert.Fail ("A1: Build should have failed");
179
180                         CheckEngineEventCounts (testLogger, 1, 1, 0, 0);
181                 }
182
183                 [Test]
184                 public void Test4 ()
185                 {
186                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
187                                 <ItemGroup>
188                                         <ResXFile Include=""Item1"">
189                                                 <Culture>fr</Culture>
190                                         </ResXFile>
191                                         <ResXFile Include=""Item5"" />
192                                         <ResXFile Include=""Item6"">
193                                                 <Culture>it</Culture>
194                                         </ResXFile>
195                                 </ItemGroup>
196
197                                 <Target Name=""ShowMessage"">
198                                         <Message
199                                                 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
200                                 </Target>
201                           </Project>";
202
203                         Engine engine = new Engine (Consts.BinPath);
204                         Project project = engine.CreateNewProject ();
205
206                         TestMessageLogger testLogger = new TestMessageLogger ();
207                         engine.RegisterLogger (testLogger);
208
209                         project.LoadXml (projectString);
210
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");
214
215                         CheckMessage (testLogger, "fr", "Item1", "A2");
216                         CheckMessage (testLogger, "", "Item5", "A3");
217                         CheckMessage (testLogger, "it", "Item6", "A3");
218                         CheckEngineEventCounts (testLogger, 1, 1, 3, 3);
219                 }
220
221                 [Test]
222                 public void TestMultiItemCollections ()
223                 {
224                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
225                                 <ItemGroup>
226                                         <ResXFile Include=""Item1"">
227                                                 <Culture>fr</Culture>
228                                         </ResXFile>
229                                         <ResXFile Include=""Item2"">
230                                                 <Culture>fr</Culture>
231                                         </ResXFile>
232                                         <ResXFile Include=""Item3"">
233                                                 <Culture>en</Culture>
234                                         </ResXFile>
235                                         <ResXFile Include=""Item4"">
236                                                 <Culture>gb</Culture>
237                                         </ResXFile>
238                                         <ResXFile Include=""Item6"">
239                                                 <Culture>it</Culture>
240                                         </ResXFile>
241
242                                         <NonResXFile Include=""Item7"">
243                                                 <Culture>it</Culture>
244                                         </NonResXFile>
245                                         <NonResXFile Include=""Item8"">
246                                                 <Culture>en</Culture>
247                                         </NonResXFile>
248                                         <NonResXFile Include=""Item9"">
249                                                 <Culture>en</Culture>
250                                         </NonResXFile>
251                                 </ItemGroup>
252
253                                 <Target Name=""ShowMessage"">
254                                         <Message
255                                                 Text = ""Culture: %(Culture) -- ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)"" />
256                                 </Target>
257                           </Project>";
258
259                         Engine engine = new Engine (Consts.BinPath);
260                         Project project = engine.CreateNewProject ();
261
262                         TestMessageLogger testLogger = new TestMessageLogger ();
263                         engine.RegisterLogger (testLogger);
264
265                         project.LoadXml (projectString);
266                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
267
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);
273                 }
274
275                 [Test]
276                 public void TestConditionalBatching ()
277                 {
278                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
279                                 <ItemGroup>
280                                         <ResXFile Include=""Item1"">
281                                                 <Culture>fr</Culture>
282                                         </ResXFile>
283                                         <ResXFile Include=""Item2"">
284                                                 <Culture>fr</Culture>
285                                         </ResXFile>
286                                         <ResXFile Include=""Item3"">
287                                                 <Culture>en</Culture>
288                                         </ResXFile>
289                                         <ResXFile Include=""Item4"">
290                                                 <Culture>gb</Culture>
291                                         </ResXFile>
292                                         <ResXFile Include=""Item6"">
293                                                 <Culture>it</Culture>
294                                         </ResXFile>
295
296                                         <NonResXFile Include=""Item7"">
297                                                 <Culture>it</Culture>
298                                         </NonResXFile>
299                                         <NonResXFile Include=""Item8"">
300                                                 <Culture>en</Culture>
301                                         </NonResXFile>
302                                         <NonResXFile Include=""Item9"">
303                                                 <Culture>en</Culture>
304                                         </NonResXFile>
305                                 </ItemGroup>
306
307                                 <Target Name=""ShowMessage"">
308                                         <Message
309                                                 Text = ""ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)""
310                                                 Condition = ""'%(Culture)' == 'fr'""/>
311                                 </Target>
312                           </Project>";
313
314                         Engine engine = new Engine (Consts.BinPath);
315                         Project project = engine.CreateNewProject ();
316
317                         TestMessageLogger testLogger = new TestMessageLogger ();
318                         engine.RegisterLogger (testLogger);
319
320                         project.LoadXml (projectString);
321                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
322
323                         testLogger.CheckLoggedMessageHead ("ResXFiles: Item1;Item2 NonResXFiles: ", "A2");
324                         CheckEngineEventCounts (testLogger, 1, 1, 1, 1);
325                 }
326
327                 [Test]
328                 public void TestMultipleMetadataReference ()
329                 {
330                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
331                                 <ItemGroup>
332                                         <ExampColl Include=""Item1"">
333                                                 <Number>1</Number>
334                                         </ExampColl>
335                                         <ExampColl Include=""Item2"">
336                                                 <Number>2</Number>
337                                         </ExampColl>
338                                         <ExampColl Include=""Item3"">
339                                         <Number>1</Number>
340                                         </ExampColl>
341
342                                         <ExampColl2 Include=""Item4"">
343                                                 <Number>1</Number>
344                                         </ExampColl2>
345                                         <ExampColl2 Include=""Item5"">
346                                                 <Number>2</Number>
347                                         <Color>Red</Color>
348                                         </ExampColl2>
349                                         <ExampColl2 Include=""Item6"">
350                                                 <Number>3</Number>
351                                         <Color>Green</Color>
352                                         </ExampColl2>
353                                 </ItemGroup>
354                                 <Target Name=""ShowMessage"">
355                                         <Message Text = ""Number: %(Number) Color: %(ExampColl2.Color)-- Items in ExampColl: @(ExampColl) ExampColl2: @(ExampColl2)""/>
356                                 </Target>
357                         </Project>";
358
359                         Engine engine = new Engine (Consts.BinPath);
360                         Project project = engine.CreateNewProject ();
361
362                         TestMessageLogger testLogger = new TestMessageLogger ();
363                         engine.RegisterLogger (testLogger);
364
365                         project.LoadXml (projectString);
366                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
367
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.NormalMessageCount, "A6");
373                         Assert.AreEqual (0, testLogger.WarningMessageCount, "A7");
374                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
375                 }
376
377                 [Test]
378                 public void TestMultipleMetadataReference2 ()
379                 {
380                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
381                                 <ItemGroup>
382                                         <GroupA Include=""file1.txt""/>
383                                         <GroupA Include=""file2.txt""/>
384                                         <GroupA Include=""file3.txt""/>
385                                         <GroupA Include=""file3.txt""/>
386                                         <GroupA Include=""file4.txt""/>
387                                 </ItemGroup>
388
389                                 <ItemGroup>
390                                         <GroupB Include=""file1.txt""/>
391                                         <GroupB Include=""file3.txt""/>
392                                         <GroupB Include=""file5.txt""/>
393
394                                         <GroupC Include=""PreExistingValue""/>
395                                 </ItemGroup>
396
397                                 <Target Name=""Build"">
398                                         <CreateItem Include=""@(GroupA)"" Condition=""'%(Identity)' != '' and '@(GroupA)' != '' and '@(GroupB)' != ''"" >
399                                                 <Output TaskParameter=""Include"" ItemName=""GroupC""/>
400                                         </CreateItem>
401                                         <Message Text=""%(GroupC.Identity)""/>
402                                 </Target>
403                         </Project>";
404
405                         Engine engine = new Engine (Consts.BinPath);
406                         Project project = engine.CreateNewProject ();
407
408                         TestMessageLogger testLogger = new TestMessageLogger ();
409                         engine.RegisterLogger (testLogger);
410
411                         project.LoadXml (projectString);
412                         Assert.IsTrue (project.Build ("Build"), "A1: Build failed");
413
414                         BuildItemGroup include = project.GetEvaluatedItemsByName ("GroupC");
415                         Assert.AreEqual (4, include.Count, "A2");
416
417                         string [,] additional_metadata = new string [,] { { "Identity", "PreExistingValue" } };
418                         CreateItemTest.CheckBuildItem (include [0], "GroupC", additional_metadata, "PreExistingValue", "A3");
419
420                         additional_metadata = new string [,] { { "Identity", "file1.txt" } };
421                         CreateItemTest.CheckBuildItem (include [1], "GroupC", additional_metadata, "file1.txt", "A4");
422
423                         additional_metadata = new string [,] { { "Identity", "file3.txt" } };
424                         CreateItemTest.CheckBuildItem (include [2], "GroupC", additional_metadata, "file3.txt", "A5");
425                         CreateItemTest.CheckBuildItem (include [3], "GroupC", additional_metadata, "file3.txt", "A6");
426
427                         CheckEngineEventCounts (testLogger, 1, 1, 5, 5);
428                 }
429
430                 [Test]
431                 public void TestIdentity ()
432                 {
433                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
434                                 <ItemGroup>
435                                         <ExampColl Include=""Item1""/>
436                                         <ExampColl Include=""Item2""/>
437                                         <ExampColl Include=""Item3""/>
438                                         <ExampColl Include=""Item4""/>
439                                         <ExampColl Include=""Item4""/>
440                                         <ExampColl Include=""Item5""/>
441                                         <ExampColl Include=""Item6""/>
442                                 </ItemGroup>
443                                 <Target Name=""ShowMessage"">
444                                         <Message Text = ""Identity: %(IdenTIty) -- Items in ExampColl: @(ExampColl)""/>
445                                 </Target>
446                         </Project>";
447
448                         Engine engine = new Engine (Consts.BinPath);
449                         Project project = engine.CreateNewProject ();
450
451                         TestMessageLogger testLogger = new TestMessageLogger ();
452                         engine.RegisterLogger (testLogger);
453
454                         project.LoadXml (projectString);
455                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
456
457                         CheckLoggedMessageAny (testLogger, "Identity: Item1 -- Items in ExampColl: Item1", "A2");
458                         CheckLoggedMessageAny (testLogger, "Identity: Item2 -- Items in ExampColl: Item2", "A3");
459                         CheckLoggedMessageAny (testLogger, "Identity: Item3 -- Items in ExampColl: Item3", "A4");
460                         CheckLoggedMessageAny (testLogger, "Identity: Item4 -- Items in ExampColl: Item4;Item4", "A5");
461                         CheckLoggedMessageAny (testLogger, "Identity: Item5 -- Items in ExampColl: Item5", "A6");
462                         CheckLoggedMessageAny (testLogger, "Identity: Item6 -- Items in ExampColl: Item6", "A7");
463                         Assert.AreEqual (0, testLogger.NormalMessageCount, "A8");
464                         Assert.AreEqual (0, testLogger.WarningMessageCount, "A7");
465                         CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
466                 }
467
468                 [Test]
469                 public void TestFilter ()
470                 {
471                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
472                                  <ItemGroup>
473                                          <fruit Include=""apple"">
474                                                  <consistency>firm</consistency>
475                                          </fruit>
476                                          <fruit Include=""orange"">
477                                                  <consistency>pulpy</consistency>
478                                          </fruit>
479                                          <fruit Include=""banana"">
480                                                  <consistency>softish</consistency>
481                                          </fruit>
482                                          <fruit Include=""pear"">
483                                                  <consistency>unsound</consistency>
484                                          </fruit>
485                                          <fruit Include=""apricot"">
486                                                  <consistency>unsound</consistency>
487                                          </fruit>
488                                  </ItemGroup>
489                                  <Target Name=""Compost"">
490                                          <CreateItem Include=""@(fruit)"" Condition=""'%(consistency)' == 'pulpy' or '%(consistency)' == 'unsound' "">
491                                                 <Output TaskParameter=""Include"" ItemName=""Final""/>
492                                          </CreateItem>
493                                  </Target>
494                          </Project>";
495
496                         Engine engine = new Engine (Consts.BinPath);
497                         Project project = engine.CreateNewProject ();
498
499                         TestMessageLogger testLogger = new TestMessageLogger ();
500                         engine.RegisterLogger (testLogger);
501
502                         project.LoadXml (projectString);
503                         Assert.IsTrue (project.Build ("Compost"), "A1: Build failed");
504
505                         BuildItemGroup include = project.GetEvaluatedItemsByName ("Final");
506                         Assert.AreEqual (3, include.Count, "A2");
507
508                         string [,] additional_metadata = new string [,] { { "Identity", "orange" } };
509                         CreateItemTest.CheckBuildItem (include [0], "Final", additional_metadata, "orange", "A3");
510
511                         additional_metadata = new string [,] { { "Identity", "pear" } };
512                         CreateItemTest.CheckBuildItem (include [1], "Final", additional_metadata, "pear", "A4");
513
514                         additional_metadata = new string [,] { { "Identity", "apricot" } };
515                         CreateItemTest.CheckBuildItem (include [2], "Final", additional_metadata, "apricot", "A5");
516                         CheckEngineEventCounts (testLogger, 1, 1, 2, 2);
517                 }
518
519                 [Test]
520                 // test for metadata refs in properties or items
521                 public void TestNoBatching () {
522                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
523         <ItemGroup>
524                 <item3 Include=""foo""/>
525                 <item2 Include=""%(item3.Identity)""/>
526                 <item0 Include=""@(item3)""/>
527         </ItemGroup>
528         <PropertyGroup>
529                 <Prop1>%(item0.Identity)</Prop1>
530         </PropertyGroup>
531         <Target Name='1'>
532                 <Message Text=""Prop1: $(Prop1)""/>
533                 <Message Text=""Item2: @(item2)""/>
534         </Target>
535 </Project>";
536
537                         Engine engine = new Engine (Consts.BinPath);
538                         Project project = engine.CreateNewProject ();
539
540                         TestMessageLogger testLogger = new TestMessageLogger ();
541                         engine.RegisterLogger (testLogger);
542
543                         project.LoadXml (projectString);
544                         if (!project.Build ("1")) {
545                                 testLogger.DumpMessages ();
546                                 Assert.Fail ("Build failed");
547                         }
548
549                         testLogger.CheckLoggedMessageHead ("Prop1: %(item0.Identity)", "A1");
550                         testLogger.CheckLoggedMessageHead ("Item2: %(item3.Identity)", "A2");
551                         Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
552                 }
553
554                 [Test]
555                 // test for metadata refs via metadata refs
556                 // batching should happen only on basis of the task attributes,
557                 // and not the resolved expression values
558                 public void TestBatching1 () {
559                         string projectString = projectHeader + @"
560         <ItemGroup>
561                 <item3 Include=""foo""/>
562                 <item2 Include=""%(item3.Identity)""/>
563
564                 <item4 Include=""%(item2.Identity);@(item3);@(nonexistant)""/>
565                 <item4 Include=""bar""/>
566         </ItemGroup>
567         <Target Name='1'>
568                 <Message Text=""Item4: %(item4.Identity)""/>
569         </Target>
570 </Project>";
571
572                         Engine engine = new Engine (Consts.BinPath);
573                         Project project = engine.CreateNewProject ();
574
575                         TestMessageLogger testLogger = new TestMessageLogger ();
576                         engine.RegisterLogger (testLogger);
577
578                         project.LoadXml (projectString);
579                         if (!project.Build ("1")) {
580                                 testLogger.DumpMessages ();
581                                 Assert.Fail ("Build failed");
582                         }
583
584                         testLogger.CheckLoggedMessageHead ("Item4: %(item2.Identity)", "A1");
585                         testLogger.CheckLoggedMessageHead ("Item4: foo", "A2");
586                         testLogger.CheckLoggedMessageHead ("Item4: bar", "A3");
587                         Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
588                 }
589
590                 [Test]
591                 // test for metadata refs via metadata refs
592                 // batching should happen only on basis of the task attributes,
593                 // and not the resolved expression values
594                 public void TestConditionalBatching2 () {
595                         string projectString = projectHeader + @"
596         <ItemGroup>
597                 <item2 Include=""%(item3.Identity)""/>
598                 <item4 Include=""%(item2.Identity);@(item3)""/>
599         </ItemGroup>
600         <Target Name='1'>
601                 <Message Text=""Item3: %(item2.Identity)"" Condition="" '%(item5.Identity)' == '' ""/>
602                 <Message Text=""Item4: %(item4.Identity)""/>
603         </Target>
604 </Project>";
605
606                         Engine engine = new Engine (Consts.BinPath);
607                         Project project = engine.CreateNewProject ();
608
609                         TestMessageLogger testLogger = new TestMessageLogger ();
610                         engine.RegisterLogger (testLogger);
611
612                         project.LoadXml (projectString);
613                         if (!project.Build ("1")) {
614                                 testLogger.DumpMessages ();
615                                 Assert.Fail ("Build failed");
616                         }
617
618                         testLogger.CheckLoggedMessageHead ("Item3: %(item3.Identity)", "A1");
619                         testLogger.CheckLoggedMessageHead ("Item4: %(item2.Identity)", "A2");
620                         Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
621                 }
622
623                 [Test]
624                 public void TestBatchingWithUnbatchedItems () {
625                         string projectString = projectHeader + @"
626         <ItemGroup>
627                 <Item1 Include=""One""/>
628                 <Item1 Include=""Two""/>
629
630                 <B Include=""abc""/>
631         </ItemGroup>
632         <Target Name='1'>
633                 <Message Text=""Item1: %(Item1.Identity) | B: @(B)""/>
634         </Target>
635 </Project>";
636
637                         Engine engine = new Engine (Consts.BinPath);
638                         Project project = engine.CreateNewProject ();
639
640                         TestMessageLogger testLogger = new TestMessageLogger ();
641                         engine.RegisterLogger (testLogger);
642
643                         project.LoadXml (projectString);
644                         if (!project.Build ("1")) {
645                                 testLogger.DumpMessages ();
646                                 Assert.Fail ("Build failed");
647                         }
648
649                         try {
650                                 testLogger.CheckLoggedMessageHead ("Item1: One | B: abc", "A1");
651                                 testLogger.CheckLoggedMessageHead ("Item1: Two | B: abc", "A2");
652
653                                 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
654                         } catch (AssertionException) {
655                                 testLogger.DumpMessages ();
656                                 throw;
657                         }
658                 }
659
660                 [Test]
661                 public void TestPropertiesWithBatchedReferences () {
662                         string projectString = projectHeader + @"
663         <ItemGroup>
664                 <Item1 Include=""One""/>
665                 <Item1 Include=""Two""/>
666
667                 <Item1Ref Include=""@(Item1)""/>
668         </ItemGroup>
669         <PropertyGroup>
670                 <Prop1>@(Item1)</Prop1>
671                 <Prop2>@(Item1Ref)</Prop2>
672         </PropertyGroup>
673         <Target Name='1'>
674                 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
675         </Target>
676 </Project>";
677
678                         Engine engine = new Engine (Consts.BinPath);
679                         Project project = engine.CreateNewProject ();
680
681                         TestMessageLogger testLogger = new TestMessageLogger ();
682                         engine.RegisterLogger (testLogger);
683
684                         project.LoadXml (projectString);
685                         if (!project.Build ("1")) {
686
687                                 testLogger.DumpMessages ();
688                                 Assert.Fail ("Build failed");
689                         }
690
691                         try {
692                                 testLogger.CheckLoggedMessageHead ("Item1: One | Prop1: One | Prop2: One;Two", "A1");
693                                 testLogger.CheckLoggedMessageHead ("Item1: Two | Prop1: Two | Prop2: One;Two", "A2");
694
695                                 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
696                         } catch (AssertionException) {
697                                 testLogger.DumpMessages ();
698                                 throw;
699                         }
700                 }
701
702                 [Test]
703                 public void TestPropertiesWithDynamicItems () {
704                         string projectString = projectHeader + @"
705         <ItemGroup>
706                 <Item1 Include=""One""/>
707                 <Item1 Include=""Two""/>
708
709                 <Item2 Include=""Z""/>
710                 <Item2Ref Include=""@(Item2)"" />
711         </ItemGroup>
712         <PropertyGroup>
713                 <Prop1>@(Item2)</Prop1>
714                 <Prop2>@(Item2Ref)</Prop2>
715         </PropertyGroup>
716         <Target Name='1'>
717                 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
718                 <Message Text=""Item2: @(Item2) | Item2Ref: @(Item2Ref)""/>
719                 <CreateItem Include=""A;B"">
720                         <Output TaskParameter=""Include"" ItemName=""Item2""/>
721                 </CreateItem>
722                 <Message Text=""Item1: %(Item1.Identity) | Prop1: $(Prop1) | Prop2: $(Prop2)""/>
723                 <Message Text=""Item2: @(Item2) | Item2Ref: @(Item2Ref)""/>
724         </Target>
725 </Project>";
726
727                         Engine engine = new Engine (Consts.BinPath);
728                         Project project = engine.CreateNewProject ();
729
730                         TestMessageLogger testLogger = new TestMessageLogger ();
731                         engine.RegisterLogger (testLogger);
732
733                         project.LoadXml (projectString);
734                         if (!project.Build ("1")) {
735
736                                 testLogger.DumpMessages ();
737                                 Assert.Fail ("Build failed");
738                         }
739
740                         try {
741
742                                 testLogger.CheckLoggedMessageHead ("Item1: One | Prop1: Z | Prop2: Z", "A1");
743                                 testLogger.CheckLoggedMessageHead ("Item1: Two | Prop1: Z | Prop2: Z", "A2");
744                                 testLogger.CheckLoggedMessageHead ("Item2: Z | Item2Ref: Z", "A3");
745
746                                 testLogger.CheckLoggedMessageHead ("Item1: One | Prop1: Z;A;B | Prop2: Z", "A4");
747                                 testLogger.CheckLoggedMessageHead ("Item1: Two | Prop1: Z;A;B | Prop2: Z", "A5");
748                                 testLogger.CheckLoggedMessageHead ("Item2: Z;A;B | Item2Ref: Z", "A3");
749
750                                 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
751                         } catch (AssertionException) {
752                                 testLogger.DumpMessages ();
753                                 throw;
754                         }
755                 }
756
757                 [Test]
758                 public void TestTargetInvocationFromBatchedTask () {
759                         string projectString = projectHeader + @"
760         <ItemGroup>
761                 <Item1 Include=""One""/>
762                 <Item1 Include=""Two""/>
763
764                 <Item1Ref Include=""@(Item1)"" />
765         </ItemGroup>
766         <PropertyGroup>
767                 <Prop1>@(Item1)</Prop1>
768                 <Prop2>@(Item1Ref)</Prop2>
769         </PropertyGroup>
770         <Target Name='1'>
771                 <CallTarget Targets='foo' Condition="" '%(Item1.Identity)' != ''"" />
772                 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
773                 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
774         </Target>
775         <Target Name='foo'>
776                 <Message Text=""(foo) Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
777                 <Message Text=""(foo) Prop1: $(Prop1) Prop2: $(Prop2)""/>
778         </Target>
779 </Project>";
780
781                         Engine engine = new Engine (Consts.BinPath);
782                         Project project = engine.CreateNewProject ();
783
784                         TestMessageLogger testLogger = new TestMessageLogger ();
785                         engine.RegisterLogger (testLogger);
786
787                         project.LoadXml (projectString);
788                         if (!project.Build ("1")) {
789
790                                 testLogger.DumpMessages ();
791                                 Assert.Fail ("Build failed");
792                         }
793
794                         try {
795                                 testLogger.CheckLoggedMessageHead ("(foo) Item1: One;Two Item1Ref: One;Two", "A1");
796                                 testLogger.CheckLoggedMessageHead ("(foo) Prop1: One;Two Prop2: One;Two", "A2");
797
798                                 testLogger.CheckLoggedMessageHead ("Item1: One;Two Item1Ref: One;Two", "A3");
799                                 testLogger.CheckLoggedMessageHead ("Prop1: One;Two Prop2: One;Two", "A4");
800
801                                 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
802                         } catch (AssertionException) {
803                                 testLogger.DumpMessages ();
804                                 throw;
805                         }
806                 }
807
808                 [Test]
809                 public void TestTargetInvocationFromBatchedTarget () {
810                         string projectString = projectHeader + @"
811         <ItemGroup>
812                 <Item1 Include=""One""/>
813                 <Item1 Include=""Two""/>
814
815                 <Item1Ref Include=""@(Item1)"" />
816         </ItemGroup>
817         <PropertyGroup>
818                 <Prop1>@(Item1)</Prop1>
819                 <Prop2>@(Item1Ref)</Prop2>
820         </PropertyGroup>
821         <Target Name='1' Inputs=""%(Item1.Identity)"" Outputs=""Nonexistant.foobar"">
822                 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
823                 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
824
825                 <CallTarget Targets='foo' />
826
827                 <Message Text=""Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
828                 <Message Text=""Prop1: $(Prop1) Prop2: $(Prop2)""/>
829         </Target>
830         <Target Name='foo' Condition="" '@(Item1)' != 'One' "">
831                 <Message Text=""(foo) Item1: @(Item1) Item1Ref: @(Item1Ref)""/>
832                 <Message Text=""(foo) Prop1: $(Prop1) Prop2: $(Prop2)""/>
833         </Target>
834 </Project>";
835
836                         Engine engine = new Engine (Consts.BinPath);
837                         Project project = engine.CreateNewProject ();
838
839                         TestMessageLogger testLogger = new TestMessageLogger ();
840                         engine.RegisterLogger (testLogger);
841
842                         project.LoadXml (projectString);
843                         if (!project.Build ("1")) {
844
845                                 testLogger.DumpMessages ();
846                                 Assert.Fail ("Build failed");
847                         }
848
849                         try {
850                                 testLogger.CheckLoggedMessageHead ("Item1: One Item1Ref: One;Two", "A1");
851                                 testLogger.CheckLoggedMessageHead ("Prop1: One Prop2: One;Two", "A2");
852
853                                 testLogger.CheckLoggedMessageHead ("(foo) Item1: One;Two Item1Ref: One;Two", "A3");
854                                 testLogger.CheckLoggedMessageHead ("(foo) Prop1: One;Two Prop2: One;Two", "A4");
855
856                                 testLogger.CheckLoggedMessageHead ("Item1: One Item1Ref: One;Two", "A5");
857                                 testLogger.CheckLoggedMessageHead ("Prop1: One Prop2: One;Two", "A6");
858
859                                 //second batch, foo has already run, so doesn't execute again
860                                 testLogger.CheckLoggedMessageHead ("Item1: Two Item1Ref: One;Two", "A7");
861                                 testLogger.CheckLoggedMessageHead ("Prop1: Two Prop2: One;Two", "A8");
862
863                                 testLogger.CheckLoggedMessageHead ("Item1: Two Item1Ref: One;Two", "A9");
864                                 testLogger.CheckLoggedMessageHead ("Prop1: Two Prop2: One;Two", "A10");
865
866                                 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
867                         } catch (AssertionException) {
868                                 testLogger.DumpMessages ();
869                                 throw;
870                         }
871                 }
872
873                 [Test]
874                 public void TestBatchingWithUnqualifiedMetadataReference () {
875                         string projectString = projectHeader + @"
876         <ItemGroup>
877                 <Item1 Include=""One""><Md>1</Md></Item1>
878                 <Item1 Include=""Two""><Md>2</Md></Item1>
879                 <Item1Ref Include=""@(Item1)"" />
880
881                 <Item2 Include=""Three""><Md>3</Md></Item2>
882                 <Item2 Include=""Four""><Md>4</Md></Item2>
883                 <Item2Ref Include=""@(Item2)"" />
884         </ItemGroup>
885         <PropertyGroup>
886                 <Prop1>@(Item1)</Prop1>
887                 <Prop1Ref>@(Item1Ref)</Prop1Ref>
888
889                 <Prop2>@(Item2)</Prop2>
890                 <Prop2Ref>@(Item2Ref)</Prop2Ref>
891         </PropertyGroup>
892         <Target Name='1'>
893                 <Message Text=""For md: %(Md) Item1: @(Item1) Item1Ref: @(Item1Ref) Item2: @(Item2) Item2Ref: @(Item2Ref) " +
894                                           @" Prop1: $(Prop1) Prop1Ref: $(Prop1Ref) Prop2: $(Prop2) Prop2Ref: $(Prop2Ref)""/>
895         </Target>
896 </Project>";
897
898                         Engine engine = new Engine (Consts.BinPath);
899                         Project project = engine.CreateNewProject ();
900
901                         TestMessageLogger testLogger = new TestMessageLogger ();
902                         engine.RegisterLogger (testLogger);
903
904                         project.LoadXml (projectString);
905                         if (!project.Build ("1")) {
906
907                                 testLogger.DumpMessages ();
908                                 Assert.Fail ("Build failed");
909                         }
910
911                         try {
912                                 testLogger.CheckLoggedAny ("For md: 3 Item1:  Item1Ref:  Item2: Three Item2Ref: Three  Prop1:  Prop1Ref:  Prop2: Three Prop2Ref: Three", MessageImportance.Normal, "A1");
913                                 testLogger.CheckLoggedAny ("For md: 4 Item1:  Item1Ref:  Item2: Four Item2Ref: Four  Prop1:  Prop1Ref:  Prop2: Four Prop2Ref: Four", MessageImportance.Normal, "A2");
914                                 testLogger.CheckLoggedAny ("For md: 1 Item1: One Item1Ref: One Item2:  Item2Ref:   Prop1: One Prop1Ref: One Prop2:  Prop2Ref: ", MessageImportance.Normal, "A3");
915                                 testLogger.CheckLoggedAny ("For md: 2 Item1: Two Item1Ref: Two Item2:  Item2Ref:   Prop1: Two Prop1Ref: Two Prop2:  Prop2Ref: ", MessageImportance.Normal, "A4");
916
917                                 Assert.AreEqual (0, testLogger.NormalMessageCount, "Unexpected extra messages found");
918                         } catch (AssertionException) {
919                                 testLogger.DumpMessages ();
920                                 throw;
921                         }
922                 }
923
924
925                 //Target batching
926
927                 [Test]
928                 public void TestTargetBatching1 ()
929                 {
930                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
931                                 <ItemGroup>
932                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
933                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
934                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
935                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
936
937                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
938                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
939
940                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
941                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
942                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
943                                 </ItemGroup>
944
945                                 <Target Name=""foo"" >
946                                         <Message Text=""TargetStarted""/>
947                                         <Message Text=""List1: @(List1): %(Culture)""/>
948                                         <Message Text=""Foo: @(Foo): %(Md)""/>
949                                 </Target>
950                 </Project>";
951
952                         Engine engine = new Engine (Consts.BinPath);
953                         Project project = engine.CreateNewProject ();
954
955                         TestMessageLogger testLogger = new TestMessageLogger ();
956                         engine.RegisterLogger (testLogger);
957
958                         project.LoadXml (projectString);
959                         bool res = project.Build ("foo");
960                         if (!res) {
961                                 testLogger.DumpMessages ();
962                                 Assert.Fail ("A1: Build failed");
963                         }
964
965                         CheckLoggedMessagesInOrder (testLogger, new string [] {
966                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
967                                 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
968                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
969                         }, "A2");
970                         CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
971                 }
972
973                 [Test]
974                 public void TestTargetBatching2 ()
975                 {
976                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
977                                 <ItemGroup>
978                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
979                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
980                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
981                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
982
983                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
984                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
985
986                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
987                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
988                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
989                                 </ItemGroup>
990
991                                 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
992                                         <Message Text=""TargetStarted""/>
993                                         <Message Text=""List1: @(List1): %(Culture)""/>
994                                         <Message Text=""Foo: @(Foo): %(Md)""/>
995                                 </Target>
996                 </Project>";
997
998                         Engine engine = new Engine (Consts.BinPath);
999                         Project project = engine.CreateNewProject ();
1000
1001                         TestMessageLogger testLogger = new TestMessageLogger ();
1002                         engine.RegisterLogger (testLogger);
1003
1004                         project.LoadXml (projectString);
1005                         bool res = project.Build ("foo");
1006                         if (!res) {
1007                                 testLogger.DumpMessages ();
1008                                 Assert.Fail ("A1: Build failed");
1009                         }
1010
1011                         CheckLoggedMessagesInOrder (testLogger, new string [] {
1012                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1013                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1014
1015                                 "TargetStarted", "List1: en_b.txt: en",
1016                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1017
1018                                 "TargetStarted", "List1: gb_d.txt: gb",
1019                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
1020                         }, "A2");
1021                         CheckEngineEventCounts (testLogger, 3, 3, 12, 12);
1022                 }
1023
1024                 [Test]
1025                 public void TestTargetBatching3 ()
1026                 {
1027                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1028                                 <ItemGroup>
1029                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1030                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1031                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1032                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1033
1034                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1035                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1036
1037                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
1038                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
1039                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
1040                                 </ItemGroup>
1041                                 <Target Name=""foo"" Inputs=""@(Foo)"" Outputs=""%(Md).foo"">
1042                                         <Message Text=""TargetStarted""/>
1043                                         <Message Text=""List1: @(List1): %(Culture)""/>
1044                                         <Message Text=""Foo: @(Foo): %(Md)""/>
1045                                 </Target>
1046                 </Project>";
1047
1048                         Engine engine = new Engine (Consts.BinPath);
1049                         Project project = engine.CreateNewProject ();
1050
1051                         TestMessageLogger testLogger = new TestMessageLogger ();
1052                         engine.RegisterLogger (testLogger);
1053
1054                         project.LoadXml (projectString);
1055                         bool res = project.Build ("foo");
1056                         if (!res) {
1057                                 testLogger.DumpMessages ();
1058                                 Assert.Fail ("A1: Build failed");
1059                         }
1060
1061                         CheckLoggedMessagesInOrder (testLogger, new string [] {
1062                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1063                                 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
1064                                 "Foo: 1_a1;1_c1: 1",
1065                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1066                                 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
1067                                 "Foo: 2_b1: 2"
1068                         }, "A2");
1069                         CheckEngineEventCounts (testLogger, 2, 2, 10, 10);
1070                 }
1071
1072                 [Test]
1073                 public void TestTargetBatching4 ()
1074                 {
1075                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1076                                 <ItemGroup>
1077                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1078                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1079                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1080                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1081
1082                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1083                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1084
1085                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
1086                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
1087                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
1088                                 </ItemGroup>
1089                                 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
1090                                         <Message Text=""TargetStarted""/>
1091                                         <Message Text=""List1: @(List1): %(Culture)""/>
1092                                         <Message Text=""List2: @(List2): %(Culture)""/>
1093                                         <Message Text=""Foo: @(Foo): %(Md)""/>
1094                                 </Target>
1095                 </Project>";
1096
1097                         Engine engine = new Engine (Consts.BinPath);
1098                         Project project = engine.CreateNewProject ();
1099
1100                         TestMessageLogger testLogger = new TestMessageLogger ();
1101                         engine.RegisterLogger (testLogger);
1102
1103                         project.LoadXml (projectString);
1104                         bool res = project.Build ("foo");
1105                         if (!res) {
1106                                 testLogger.DumpMessages ();
1107                                 Assert.Fail ("A1: Build failed");
1108                         }
1109
1110                         CheckLoggedMessagesInOrder (testLogger, new string [] {
1111                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
1112                                 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1113                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1114
1115                                 "TargetStarted", "List1: en_b.txt: en",
1116                                 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1117                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
1118
1119                                 "TargetStarted", "List1: gb_d.txt: gb",
1120                                 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
1121                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
1122                         }, "A2");
1123                         CheckEngineEventCounts (testLogger, 3, 3, 18, 18);
1124                 }
1125
1126                 [Test]
1127                 public void TestTargetBatching5 ()
1128                 {
1129                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1130                                 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
1131                                         <Message Text=""TargetStarted""/>
1132                                 </Target>
1133                         </Project>";
1134
1135                         Engine engine = new Engine (Consts.BinPath);
1136                         Project project = engine.CreateNewProject ();
1137
1138                         TestMessageLogger testLogger = new TestMessageLogger ();
1139                         engine.RegisterLogger (testLogger);
1140
1141                         project.LoadXml (projectString);
1142                         bool res = project.Build ("foo");
1143                         if (!res) {
1144                                 testLogger.DumpMessages ();
1145                                 Assert.Fail ("A1: Build failed");
1146                         }
1147                         Assert.AreEqual (1, testLogger.CheckAny ("TargetStarted", MessageImportance.Normal),
1148                                 "A2: Target should've been skipped because of no inputs");
1149                         CheckEngineEventCounts (testLogger, 1, 1, 0, 0);
1150                 }
1151
1152                 [Test]
1153                 public void TestTargetBatching6 ()
1154                 {
1155                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1156                                 <ItemGroup>
1157                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1158                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1159                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1160                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1161
1162                                         <List3 Include=""fr_x.txt""><Culture>fr</Culture></List3>
1163                                         <List3 Include=""gb_z.txt""><Culture>gb</Culture></List3>
1164
1165                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
1166                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
1167                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
1168                                 </ItemGroup>
1169
1170                                 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
1171                                         <Message Text=""TargetStarted"" />
1172                                         <Message Text=""List1: %(List1.Culture), List2: %(List2.Culture)"" />
1173                                         <Message Text=""List2: @(List2), Culture: %(Culture)"" />
1174                                         <Message Text=""List3: @(List3), Culture: %(Culture)"" />
1175                                 </Target>
1176                         </Project>";
1177
1178                         Engine engine = new Engine (Consts.BinPath);
1179                         Project project = engine.CreateNewProject ();
1180
1181                         TestMessageLogger testLogger = new TestMessageLogger ();
1182                         engine.RegisterLogger (testLogger);
1183
1184                         project.LoadXml (projectString);
1185                         bool res = project.Build ("foo");
1186                         if (!res) {
1187                                 testLogger.DumpMessages ();
1188                                 Assert.Fail ("A1: Build failed");
1189                         }
1190
1191                         CheckLoggedMessagesInOrder (testLogger, new string [] {
1192                                 "TargetStarted",
1193                                 "List1: fr, List2: ",
1194                                 "List2: , Culture: ",
1195                                 "List3: fr_x.txt, Culture: fr",
1196                                 "List3: gb_z.txt, Culture: gb",
1197
1198                                 "TargetStarted",
1199                                 "List1: en, List2: ",
1200                                 "List2: , Culture: ",
1201                                 "List3: fr_x.txt, Culture: fr",
1202                                 "List3: gb_z.txt, Culture: gb",
1203
1204                                 "TargetStarted",
1205                                 "List1: gb, List2: ",
1206                                 "List2: , Culture: ",
1207                                 "List3: fr_x.txt, Culture: fr",
1208                                 "List3: gb_z.txt, Culture: gb"
1209                         }, "A2");
1210                         CheckEngineEventCounts (testLogger, 3, 3, 15, 15);
1211                 }
1212
1213                 [Test]
1214                 public void TestTargetBatching7 ()
1215                 {
1216                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
1217                                 <ItemGroup>
1218                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
1219                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
1220                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
1221                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
1222
1223                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
1224                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
1225
1226                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
1227                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
1228                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
1229                                 </ItemGroup>
1230
1231                                 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
1232                                         <Message Text=""TargetStarted"" />
1233                                         <Message Text=""List1: @(List1), List2: @(List2)""/>
1234                                 </Target>
1235                         </Project>";
1236
1237                         Engine engine = new Engine (Consts.BinPath);
1238                         Project project = engine.CreateNewProject ();
1239
1240                         TestMessageLogger testLogger = new TestMessageLogger ();
1241                         engine.RegisterLogger (testLogger);
1242
1243                         project.LoadXml (projectString);
1244                         bool res = project.Build ("foo");
1245                         if (!res) {
1246                                 testLogger.DumpMessages ();
1247                                 Assert.Fail ("A1: Build failed");
1248                         }
1249
1250                         CheckLoggedMessagesInOrder (testLogger, new string [] {
1251                                 "TargetStarted",
1252                                 "List1: fr_a.txt;fr_c.txt, List2: fr_x.txt",
1253
1254                                 "TargetStarted",
1255                                 "List1: en_b.txt, List2: ",
1256
1257                                 "TargetStarted",
1258                                 "List1: gb_d.txt, List2: gb_z.txt"
1259                         }, "A2");
1260                         CheckEngineEventCounts (testLogger, 3, 3, 6, 6);
1261                 }
1262
1263                 void CheckLoggedMessagesInOrder (TestMessageLogger logger, string [] values, string prefix)
1264                 {
1265                         try {
1266                                 for (int i = 0; i < values.Length; i++) {
1267                                         logger.CheckLoggedMessageHead (values [i], prefix + "#" + i);
1268                                 }
1269                                 if (logger.NormalMessageCount > 0)
1270                                         Assert.Fail ("{0}: Expected {1} messages, but found {2}",
1271                                                 prefix, values.Length, values.Length + logger.NormalMessageCount);
1272                         } catch (NUnit.Framework.AssertionException) {
1273                                 logger.DumpMessages ();
1274                                 throw;
1275                         }
1276                 }
1277
1278                 void CheckMessage (TestMessageLogger logger, string culture, string items, string id)
1279                 {
1280                         logger.CheckLoggedMessageHead (String.Format ("Culture: {0} -- ResXFile: {1}", culture, items), id);
1281                 }
1282
1283                 void CheckMessage2 (TestMessageLogger logger, string culture, string resx_files, string nonresx_files, string id)
1284                 {
1285                         logger.CheckLoggedMessageHead (String.Format ("Culture: {0} -- ResXFiles: {1} NonResXFiles: {2}", culture, resx_files, nonresx_files), id);
1286                 }
1287
1288                 void CheckLoggedMessageAny (TestMessageLogger logger, string expected, string id)
1289                 {
1290                         if (logger.CheckAny (expected, MessageImportance.Normal) == 1)
1291                                 Assert.Fail ("{0}: Expected message '{1}' was not emitted.", id, expected);
1292                 }
1293
1294                 void CheckEngineEventCounts (TestMessageLogger logger, int target_start, int target_finish, int task_start, int task_finish)
1295                 {
1296                         Assert.AreEqual (target_start, logger.TargetStarted, "TargetStarted event count doesn't match");
1297                         Assert.AreEqual (target_finish, logger.TargetFinished, "TargetFinished event count doesn't match");
1298                         Assert.AreEqual (task_start, logger.TaskStarted, "TaskStarted event count doesn't match");
1299                         Assert.AreEqual (task_finish, logger.TaskFinished, "TaskFinished event count doesn't match");
1300                 }
1301         }
1302 }