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