Lazily load UsingTask tasks.
[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 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 using System;
29 using System.Collections.Generic;
30 using System.Text;
31 using NUnit.Framework;
32 using Microsoft.Build.BuildEngine;
33 using Microsoft.Build.Framework;
34 using Microsoft.Build.Tasks;
35 using Microsoft.Build.Utilities;
36
37 namespace MonoTests.Microsoft.Build.Tasks
38 {
39         [TestFixture]
40         public class TaskBatchingTest
41         {
42                 [Test]
43                 public void Test1 ()
44                 {
45                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
46                                 <ItemGroup>
47                                         <ResXFile Include=""Item1"">
48                                                 <Culture>fr</Culture>
49                                         </ResXFile>
50                                         <ResXFile Include=""Item2"">
51                                                 <Culture>fr</Culture>
52                                         </ResXFile>
53                                         <ResXFile Include=""Item3"">
54                                                 <Culture>en</Culture>
55                                         </ResXFile>
56                                         <ResXFile Include=""Item4"">
57                                                 <Culture>gb</Culture>
58                                         </ResXFile>
59                                         <ResXFile Include=""Item5"">
60                                                 <Culture>fr</Culture>
61                                         </ResXFile>
62                                         <ResXFile Include=""Item6"">
63                                                 <Culture>it</Culture>
64                                         </ResXFile>
65                                 </ItemGroup>
66
67                                 <Target Name=""ShowMessage"">
68                                         <Message
69                                                 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
70                                 </Target>
71                           </Project>";
72
73                         Engine engine = new Engine (Consts.BinPath);
74                         Project project = engine.CreateNewProject ();
75
76                         TestMessageLogger testLogger = new TestMessageLogger ();
77                         engine.RegisterLogger (testLogger);
78
79                         project.LoadXml (projectString);
80                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
81
82                         CheckMessage (testLogger, "fr", "Item1;Item2;Item5", "A2");
83                         CheckMessage (testLogger, "en", "Item3", "A3");
84                         CheckMessage (testLogger, "gb", "Item4", "A4");
85                         CheckMessage (testLogger, "it", "Item6", "A5");
86
87                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
88                 }
89
90                 // Test1 with unqualified %(Culture)
91                 [Test]
92                 public void Test2 ()
93                 {
94                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
95                                 <ItemGroup>
96                                         <ResXFile Include=""Item1"">
97                                                 <Culture>fr</Culture>
98                                         </ResXFile>
99                                         <ResXFile Include=""Item2"">
100                                                 <Culture>fr</Culture>
101                                         </ResXFile>
102                                         <ResXFile Include=""Item3"">
103                                                 <Culture>en</Culture>
104                                         </ResXFile>
105                                         <ResXFile Include=""Item4"">
106                                                 <Culture>gb</Culture>
107                                         </ResXFile>
108                                         <ResXFile Include=""Item5"">
109                                                 <Culture>fr</Culture>
110                                         </ResXFile>
111                                         <ResXFile Include=""Item6"">
112                                                 <Culture>it</Culture>
113                                         </ResXFile>
114                                 </ItemGroup>
115
116                                 <Target Name=""ShowMessage"">
117                                         <Message
118                                                 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
119                                 </Target>
120                           </Project>";
121
122                         Engine engine = new Engine (Consts.BinPath);
123                         Project project = engine.CreateNewProject ();
124
125                         TestMessageLogger testLogger = new TestMessageLogger ();
126                         engine.RegisterLogger (testLogger);
127
128                         project.LoadXml (projectString);
129                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
130
131                         CheckMessage (testLogger, "fr", "Item1;Item2;Item5", "A2");
132                         CheckMessage (testLogger, "en", "Item3", "A3");
133                         CheckMessage (testLogger, "gb", "Item4", "A4");
134                         CheckMessage (testLogger, "it", "Item6", "A5");
135
136                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
137                 }
138
139                 [Test]
140                 public void TestUnqualifiedMetadataReference ()
141                 {
142                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
143                                 <ItemGroup>
144                                         <ResXFile Include=""Item1"">
145                                                 <Culture>fr</Culture>
146                                         </ResXFile>
147                                         <ResXFile Include=""Item5"" />
148                                         <ResXFile Include=""Item6"">
149                                                 <Culture>it</Culture>
150                                         </ResXFile>
151                                 </ItemGroup>
152
153                                 <Target Name=""ShowMessage"">
154                                         <Message
155                                                 Text = ""Culture: %(Culture) -- ResXFile: @(ResXFile)"" />
156                                 </Target>
157                           </Project>";
158
159                         Engine engine = new Engine (Consts.BinPath);
160                         Project project = engine.CreateNewProject ();
161
162                         TestMessageLogger testLogger = new TestMessageLogger ();
163                         engine.RegisterLogger (testLogger);
164
165                         project.LoadXml (projectString);
166
167                         //Fails as Culture is being referenced unqualified, and no Culture is
168                         //specified for "Item5"
169                         bool result = project.Build ("ShowMessage");
170                         if (result)
171                                 Assert.Fail ("A1: Build should have failed");
172
173                         CheckEngineEventCounts (testLogger, 1, 1, 0, 0);
174                 }
175
176                 [Test]
177                 public void Test4 ()
178                 {
179                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
180                                 <ItemGroup>
181                                         <ResXFile Include=""Item1"">
182                                                 <Culture>fr</Culture>
183                                         </ResXFile>
184                                         <ResXFile Include=""Item5"" />
185                                         <ResXFile Include=""Item6"">
186                                                 <Culture>it</Culture>
187                                         </ResXFile>
188                                 </ItemGroup>
189
190                                 <Target Name=""ShowMessage"">
191                                         <Message
192                                                 Text = ""Culture: %(ResXFile.Culture) -- ResXFile: @(ResXFile)"" />
193                                 </Target>
194                           </Project>";
195
196                         Engine engine = new Engine (Consts.BinPath);
197                         Project project = engine.CreateNewProject ();
198
199                         TestMessageLogger testLogger = new TestMessageLogger ();
200                         engine.RegisterLogger (testLogger);
201
202                         project.LoadXml (projectString);
203
204                         //no Culture is specified for "Item5", but
205                         //Culture is being referenced __qualified__, so works
206                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
207
208                         CheckMessage (testLogger, "fr", "Item1", "A2");
209                         CheckMessage (testLogger, "", "Item5", "A3");
210                         CheckMessage (testLogger, "it", "Item6", "A3");
211                         CheckEngineEventCounts (testLogger, 1, 1, 3, 3);
212                 }
213
214                 [Test]
215                 public void TestMultiItemCollections ()
216                 {
217                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
218                                 <ItemGroup>
219                                         <ResXFile Include=""Item1"">
220                                                 <Culture>fr</Culture>
221                                         </ResXFile>
222                                         <ResXFile Include=""Item2"">
223                                                 <Culture>fr</Culture>
224                                         </ResXFile>
225                                         <ResXFile Include=""Item3"">
226                                                 <Culture>en</Culture>
227                                         </ResXFile>
228                                         <ResXFile Include=""Item4"">
229                                                 <Culture>gb</Culture>
230                                         </ResXFile>
231                                         <ResXFile Include=""Item6"">
232                                                 <Culture>it</Culture>
233                                         </ResXFile>
234
235                                         <NonResXFile Include=""Item7"">
236                                                 <Culture>it</Culture>
237                                         </NonResXFile>
238                                         <NonResXFile Include=""Item8"">
239                                                 <Culture>en</Culture>
240                                         </NonResXFile>
241                                         <NonResXFile Include=""Item9"">
242                                                 <Culture>en</Culture>
243                                         </NonResXFile>
244                                 </ItemGroup>
245
246                                 <Target Name=""ShowMessage"">
247                                         <Message
248                                                 Text = ""Culture: %(Culture) -- ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)"" />
249                                 </Target>
250                           </Project>";
251
252                         Engine engine = new Engine (Consts.BinPath);
253                         Project project = engine.CreateNewProject ();
254
255                         TestMessageLogger testLogger = new TestMessageLogger ();
256                         engine.RegisterLogger (testLogger);
257
258                         project.LoadXml (projectString);
259                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
260
261                         CheckMessage2 (testLogger, "fr", "Item1;Item2", string.Empty, "A2");
262                         CheckMessage2 (testLogger, "en", "Item3", "Item8;Item9", "A3");
263                         CheckMessage2 (testLogger, "gb", "Item4", string.Empty, "A4");
264                         CheckMessage2 (testLogger, "it", "Item6", "Item7", "A6");
265                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
266                 }
267
268                 [Test]
269                 public void TestConditionalBatching ()
270                 {
271                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
272                                 <ItemGroup>
273                                         <ResXFile Include=""Item1"">
274                                                 <Culture>fr</Culture>
275                                         </ResXFile>
276                                         <ResXFile Include=""Item2"">
277                                                 <Culture>fr</Culture>
278                                         </ResXFile>
279                                         <ResXFile Include=""Item3"">
280                                                 <Culture>en</Culture>
281                                         </ResXFile>
282                                         <ResXFile Include=""Item4"">
283                                                 <Culture>gb</Culture>
284                                         </ResXFile>
285                                         <ResXFile Include=""Item6"">
286                                                 <Culture>it</Culture>
287                                         </ResXFile>
288
289                                         <NonResXFile Include=""Item7"">
290                                                 <Culture>it</Culture>
291                                         </NonResXFile>
292                                         <NonResXFile Include=""Item8"">
293                                                 <Culture>en</Culture>
294                                         </NonResXFile>
295                                         <NonResXFile Include=""Item9"">
296                                                 <Culture>en</Culture>
297                                         </NonResXFile>
298                                 </ItemGroup>
299
300                                 <Target Name=""ShowMessage"">
301                                         <Message
302                                                 Text = ""ResXFiles: @(ResXFile) NonResXFiles: @(NonResXFile)""
303                                                 Condition = ""'%(Culture)' == 'fr'""/>
304                                 </Target>
305                           </Project>";
306
307                         Engine engine = new Engine (Consts.BinPath);
308                         Project project = engine.CreateNewProject ();
309
310                         TestMessageLogger testLogger = new TestMessageLogger ();
311                         engine.RegisterLogger (testLogger);
312
313                         project.LoadXml (projectString);
314                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
315
316                         testLogger.CheckLoggedMessageHead ("ResXFiles: Item1;Item2 NonResXFiles: ", "A2");
317                         CheckEngineEventCounts (testLogger, 1, 1, 1, 1);
318                 }
319
320                 [Test]
321                 public void TestMultipleMetadataReference ()
322                 {
323                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
324                                 <ItemGroup>
325                                         <ExampColl Include=""Item1"">
326                                                 <Number>1</Number>
327                                         </ExampColl>
328                                         <ExampColl Include=""Item2"">
329                                                 <Number>2</Number>
330                                         </ExampColl>
331                                         <ExampColl Include=""Item3"">
332                                         <Number>1</Number>
333                                         </ExampColl>
334
335                                         <ExampColl2 Include=""Item4"">
336                                                 <Number>1</Number>
337                                         </ExampColl2>
338                                         <ExampColl2 Include=""Item5"">
339                                                 <Number>2</Number>
340                                         <Color>Red</Color>
341                                         </ExampColl2>
342                                         <ExampColl2 Include=""Item6"">
343                                                 <Number>3</Number>
344                                         <Color>Green</Color>
345                                         </ExampColl2>
346                                 </ItemGroup>
347                                 <Target Name=""ShowMessage"">
348                                         <Message Text = ""Number: %(Number) Color: %(ExampColl2.Color)-- Items in ExampColl: @(ExampColl) ExampColl2: @(ExampColl2)""/>
349                                 </Target>
350                         </Project>";
351
352                         Engine engine = new Engine (Consts.BinPath);
353                         Project project = engine.CreateNewProject ();
354
355                         TestMessageLogger testLogger = new TestMessageLogger ();
356                         engine.RegisterLogger (testLogger);
357
358                         project.LoadXml (projectString);
359                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
360
361                         CheckLoggedMessageAny (testLogger, "Number: 1 Color: -- Items in ExampColl: Item1;Item3 ExampColl2: Item4", "A2");
362                         CheckLoggedMessageAny (testLogger, "Number: 2 Color: Red-- Items in ExampColl:  ExampColl2: Item5", "A3");
363                         CheckLoggedMessageAny (testLogger, "Number: 3 Color: Green-- Items in ExampColl:  ExampColl2: Item6", "A4");
364                         CheckLoggedMessageAny (testLogger, "Number: 2 Color: -- Items in ExampColl: Item2 ExampColl2: ", "A5");
365                         Assert.AreEqual (0, testLogger.Count, "A6");
366                         CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
367                 }
368
369                 [Test]
370                 public void TestMultipleMetadataReference2 ()
371                 {
372                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
373                                 <ItemGroup>
374                                         <GroupA Include=""file1.txt""/>
375                                         <GroupA Include=""file2.txt""/>
376                                         <GroupA Include=""file3.txt""/>
377                                         <GroupA Include=""file3.txt""/>
378                                         <GroupA Include=""file4.txt""/>
379                                 </ItemGroup>
380
381                                 <ItemGroup>
382                                         <GroupB Include=""file1.txt""/>
383                                         <GroupB Include=""file3.txt""/>
384                                         <GroupB Include=""file5.txt""/>
385
386                                         <GroupC Include=""PreExistingValue""/>
387                                 </ItemGroup>
388
389                                 <Target Name=""Build"">
390                                         <CreateItem Include=""@(GroupA)"" Condition=""'%(Identity)' != '' and '@(GroupA)' != '' and '@(GroupB)' != ''"" >
391                                                 <Output TaskParameter=""Include"" ItemName=""GroupC""/>
392                                         </CreateItem>
393                                         <Message Text=""%(GroupC.Identity)""/>
394                                 </Target>
395                         </Project>";
396
397                         Engine engine = new Engine (Consts.BinPath);
398                         Project project = engine.CreateNewProject ();
399
400                         TestMessageLogger testLogger = new TestMessageLogger ();
401                         engine.RegisterLogger (testLogger);
402
403                         project.LoadXml (projectString);
404                         Assert.IsTrue (project.Build ("Build"), "A1: Build failed");
405
406                         BuildItemGroup include = project.GetEvaluatedItemsByName ("GroupC");
407                         Assert.AreEqual (4, include.Count, "A2");
408
409                         string [,] additional_metadata = new string [,] { { "Identity", "PreExistingValue" } };
410                         CreateItemTest.CheckBuildItem (include [0], "GroupC", additional_metadata, "PreExistingValue", "A3");
411
412                         additional_metadata = new string [,] { { "Identity", "file1.txt" } };
413                         CreateItemTest.CheckBuildItem (include [1], "GroupC", additional_metadata, "file1.txt", "A4");
414
415                         additional_metadata = new string [,] { { "Identity", "file3.txt" } };
416                         CreateItemTest.CheckBuildItem (include [2], "GroupC", additional_metadata, "file3.txt", "A5");
417                         CreateItemTest.CheckBuildItem (include [3], "GroupC", additional_metadata, "file3.txt", "A6");
418
419                         CheckEngineEventCounts (testLogger, 1, 1, 5, 5);
420                 }
421
422                 [Test]
423                 public void TestIdentity ()
424                 {
425                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
426                                 <ItemGroup>
427                                         <ExampColl Include=""Item1""/>
428                                         <ExampColl Include=""Item2""/>
429                                         <ExampColl Include=""Item3""/>
430                                         <ExampColl Include=""Item4""/>
431                                         <ExampColl Include=""Item4""/>
432                                         <ExampColl Include=""Item5""/>
433                                         <ExampColl Include=""Item6""/>
434                                 </ItemGroup>
435                                 <Target Name=""ShowMessage"">
436                                         <Message Text = ""Identity: %(IdenTIty) -- Items in ExampColl: @(ExampColl)""/>
437                                 </Target>
438                         </Project>";
439
440                         Engine engine = new Engine (Consts.BinPath);
441                         Project project = engine.CreateNewProject ();
442
443                         TestMessageLogger testLogger = new TestMessageLogger ();
444                         engine.RegisterLogger (testLogger);
445
446                         project.LoadXml (projectString);
447                         Assert.IsTrue (project.Build ("ShowMessage"), "A1: Build failed");
448
449                         CheckLoggedMessageAny (testLogger, "Identity: Item1 -- Items in ExampColl: Item1", "A2");
450                         CheckLoggedMessageAny (testLogger, "Identity: Item2 -- Items in ExampColl: Item2", "A3");
451                         CheckLoggedMessageAny (testLogger, "Identity: Item3 -- Items in ExampColl: Item3", "A4");
452                         CheckLoggedMessageAny (testLogger, "Identity: Item4 -- Items in ExampColl: Item4;Item4", "A5");
453                         CheckLoggedMessageAny (testLogger, "Identity: Item5 -- Items in ExampColl: Item5", "A6");
454                         CheckLoggedMessageAny (testLogger, "Identity: Item6 -- Items in ExampColl: Item6", "A7");
455                         Assert.AreEqual (0, testLogger.Count, "A8");
456                         CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
457                 }
458
459                 [Test]
460                 public void TestFilter ()
461                 {
462                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
463                                  <ItemGroup>
464                                          <fruit Include=""apple"">
465                                                  <consistency>firm</consistency>
466                                          </fruit>
467                                          <fruit Include=""orange"">
468                                                  <consistency>pulpy</consistency>
469                                          </fruit>
470                                          <fruit Include=""banana"">
471                                                  <consistency>softish</consistency>
472                                          </fruit>
473                                          <fruit Include=""pear"">
474                                                  <consistency>unsound</consistency>
475                                          </fruit>
476                                          <fruit Include=""apricot"">
477                                                  <consistency>unsound</consistency>
478                                          </fruit>
479                                  </ItemGroup>
480                                  <Target Name=""Compost"">
481                                          <CreateItem Include=""@(fruit)"" Condition=""'%(consistency)' == 'pulpy' or '%(consistency)' == 'unsound' "">
482                                                 <Output TaskParameter=""Include"" ItemName=""Final""/>
483                                          </CreateItem>
484                                  </Target>
485                          </Project>";
486
487                         Engine engine = new Engine (Consts.BinPath);
488                         Project project = engine.CreateNewProject ();
489
490                         TestMessageLogger testLogger = new TestMessageLogger ();
491                         engine.RegisterLogger (testLogger);
492
493                         project.LoadXml (projectString);
494                         Assert.IsTrue (project.Build ("Compost"), "A1: Build failed");
495
496                         BuildItemGroup include = project.GetEvaluatedItemsByName ("Final");
497                         Assert.AreEqual (3, include.Count, "A2");
498
499                         string [,] additional_metadata = new string [,] { { "Identity", "orange" } };
500                         CreateItemTest.CheckBuildItem (include [0], "Final", additional_metadata, "orange", "A3");
501
502                         additional_metadata = new string [,] { { "Identity", "pear" } };
503                         CreateItemTest.CheckBuildItem (include [1], "Final", additional_metadata, "pear", "A4");
504
505                         additional_metadata = new string [,] { { "Identity", "apricot" } };
506                         CreateItemTest.CheckBuildItem (include [2], "Final", additional_metadata, "apricot", "A5");
507                         CheckEngineEventCounts (testLogger, 1, 1, 2, 2);
508                 }
509
510                 //Target batching
511
512                 [Test]
513                 public void TestTargetBatching1 ()
514                 {
515                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
516                                 <ItemGroup>
517                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
518                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
519                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
520                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
521
522                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
523                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
524
525                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
526                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
527                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
528                                 </ItemGroup>
529
530                                 <Target Name=""foo"" >
531                                         <Message Text=""TargetStarted""/>
532                                         <Message Text=""List1: @(List1): %(Culture)""/>
533                                         <Message Text=""Foo: @(Foo): %(Md)""/>
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                         bool res = project.Build ("foo");
545                         if (!res) {
546                                 testLogger.DumpMessages ();
547                                 Assert.Fail ("A1: Build failed");
548                         }
549
550                         CheckLoggedMessagesInOrder (testLogger, new string [] {
551                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
552                                 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
553                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
554                         }, "A2");
555                         CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
556                 }
557
558                 [Test]
559                 public void TestTargetBatching2 ()
560                 {
561                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
562                                 <ItemGroup>
563                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
564                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
565                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
566                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
567
568                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
569                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
570
571                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
572                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
573                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
574                                 </ItemGroup>
575
576                                 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
577                                         <Message Text=""TargetStarted""/>
578                                         <Message Text=""List1: @(List1): %(Culture)""/>
579                                         <Message Text=""Foo: @(Foo): %(Md)""/>
580                                 </Target>
581                 </Project>";
582
583                         Engine engine = new Engine (Consts.BinPath);
584                         Project project = engine.CreateNewProject ();
585
586                         TestMessageLogger testLogger = new TestMessageLogger ();
587                         engine.RegisterLogger (testLogger);
588
589                         project.LoadXml (projectString);
590                         bool res = project.Build ("foo");
591                         if (!res) {
592                                 testLogger.DumpMessages ();
593                                 Assert.Fail ("A1: Build failed");
594                         }
595
596                         CheckLoggedMessagesInOrder (testLogger, new string [] {
597                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
598                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
599
600                                 "TargetStarted", "List1: en_b.txt: en",
601                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
602
603                                 "TargetStarted", "List1: gb_d.txt: gb",
604                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
605                         }, "A2");
606                         CheckEngineEventCounts (testLogger, 3, 3, 12, 12);
607                 }
608
609                 [Test]
610                 public void TestTargetBatching3 ()
611                 {
612                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
613                                 <ItemGroup>
614                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
615                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
616                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
617                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
618
619                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
620                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
621
622                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
623                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
624                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
625                                 </ItemGroup>
626                                 <Target Name=""foo"" Inputs=""@(Foo)"" Outputs=""%(Md).foo"">
627                                         <Message Text=""TargetStarted""/>
628                                         <Message Text=""List1: @(List1): %(Culture)""/>
629                                         <Message Text=""Foo: @(Foo): %(Md)""/>
630                                 </Target>
631                 </Project>";
632
633                         Engine engine = new Engine (Consts.BinPath);
634                         Project project = engine.CreateNewProject ();
635
636                         TestMessageLogger testLogger = new TestMessageLogger ();
637                         engine.RegisterLogger (testLogger);
638
639                         project.LoadXml (projectString);
640                         bool res = project.Build ("foo");
641                         if (!res) {
642                                 testLogger.DumpMessages ();
643                                 Assert.Fail ("A1: Build failed");
644                         }
645
646                         CheckLoggedMessagesInOrder (testLogger, new string [] {
647                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
648                                 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
649                                 "Foo: 1_a1;1_c1: 1",
650                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
651                                 "List1: en_b.txt: en", "List1: gb_d.txt: gb",
652                                 "Foo: 2_b1: 2"
653                         }, "A2");
654                         CheckEngineEventCounts (testLogger, 2, 2, 10, 10);
655                 }
656
657                 [Test]
658                 public void TestTargetBatching4 ()
659                 {
660                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
661                                 <ItemGroup>
662                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
663                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
664                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
665                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
666
667                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
668                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
669
670                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
671                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
672                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
673                                 </ItemGroup>
674                                 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
675                                         <Message Text=""TargetStarted""/>
676                                         <Message Text=""List1: @(List1): %(Culture)""/>
677                                         <Message Text=""List2: @(List2): %(Culture)""/>
678                                         <Message Text=""Foo: @(Foo): %(Md)""/>
679                                 </Target>
680                 </Project>";
681
682                         Engine engine = new Engine (Consts.BinPath);
683                         Project project = engine.CreateNewProject ();
684
685                         TestMessageLogger testLogger = new TestMessageLogger ();
686                         engine.RegisterLogger (testLogger);
687
688                         project.LoadXml (projectString);
689                         bool res = project.Build ("foo");
690                         if (!res) {
691                                 testLogger.DumpMessages ();
692                                 Assert.Fail ("A1: Build failed");
693                         }
694
695                         CheckLoggedMessagesInOrder (testLogger, new string [] {
696                                 "TargetStarted", "List1: fr_a.txt;fr_c.txt: fr",
697                                 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
698                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
699
700                                 "TargetStarted", "List1: en_b.txt: en",
701                                 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
702                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2",
703
704                                 "TargetStarted", "List1: gb_d.txt: gb",
705                                 "List2: fr_x.txt: fr", "List2: gb_z.txt: gb",
706                                 "Foo: 1_a1;1_c1: 1", "Foo: 2_b1: 2"
707                         }, "A2");
708                         CheckEngineEventCounts (testLogger, 3, 3, 18, 18);
709                 }
710
711                 [Test]
712                 public void TestTargetBatching5 ()
713                 {
714                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
715                                 <Target Name=""foo"" Inputs=""@(List1)"" Outputs=""%(Culture).foo"">
716                                         <Message Text=""TargetStarted""/>
717                                 </Target>
718                         </Project>";
719
720                         Engine engine = new Engine (Consts.BinPath);
721                         Project project = engine.CreateNewProject ();
722
723                         TestMessageLogger testLogger = new TestMessageLogger ();
724                         engine.RegisterLogger (testLogger);
725
726                         project.LoadXml (projectString);
727                         bool res = project.Build ("foo");
728                         if (!res) {
729                                 testLogger.DumpMessages ();
730                                 Assert.Fail ("A1: Build failed");
731                         }
732                         Assert.AreEqual (1, testLogger.CheckAny ("TargetStarted", MessageImportance.Normal),
733                                 "A2: Target should've been skipped because of no inputs");
734                         CheckEngineEventCounts (testLogger, 1, 1, 0, 0);
735                 }
736
737                 [Test]
738                 public void TestTargetBatching6 ()
739                 {
740                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
741                                 <ItemGroup>
742                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
743                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
744                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
745                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
746
747                                         <List3 Include=""fr_x.txt""><Culture>fr</Culture></List3>
748                                         <List3 Include=""gb_z.txt""><Culture>gb</Culture></List3>
749
750                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
751                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
752                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
753                                 </ItemGroup>
754
755                                 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
756                                         <Message Text=""TargetStarted"" />
757                                         <Message Text=""List1: %(List1.Culture), List2: %(List2.Culture)"" />
758                                         <Message Text=""List2: @(List2), Culture: %(Culture)"" />
759                                         <Message Text=""List3: @(List3), Culture: %(Culture)"" />
760                                 </Target>
761                         </Project>";
762
763                         Engine engine = new Engine (Consts.BinPath);
764                         Project project = engine.CreateNewProject ();
765
766                         TestMessageLogger testLogger = new TestMessageLogger ();
767                         engine.RegisterLogger (testLogger);
768
769                         project.LoadXml (projectString);
770                         bool res = project.Build ("foo");
771                         if (!res) {
772                                 testLogger.DumpMessages ();
773                                 Assert.Fail ("A1: Build failed");
774                         }
775
776                         CheckLoggedMessagesInOrder (testLogger, new string [] {
777                                 "TargetStarted",
778                                 "List1: fr, List2: ",
779                                 "List2: , Culture: ",
780                                 "List3: fr_x.txt, Culture: fr",
781                                 "List3: gb_z.txt, Culture: gb",
782
783                                 "TargetStarted",
784                                 "List1: en, List2: ",
785                                 "List2: , Culture: ",
786                                 "List3: fr_x.txt, Culture: fr",
787                                 "List3: gb_z.txt, Culture: gb",
788
789                                 "TargetStarted",
790                                 "List1: gb, List2: ",
791                                 "List2: , Culture: ",
792                                 "List3: fr_x.txt, Culture: fr",
793                                 "List3: gb_z.txt, Culture: gb"
794                         }, "A2");
795                         CheckEngineEventCounts (testLogger, 3, 3, 15, 15);
796                 }
797
798                 [Test]
799                 public void TestTargetBatching7 ()
800                 {
801                         string projectString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
802                                 <ItemGroup>
803                                         <List1 Include=""fr_a.txt""><Culture>fr</Culture></List1>
804                                         <List1 Include=""en_b.txt""><Culture>en</Culture></List1>
805                                         <List1 Include=""fr_c.txt""><Culture>fr</Culture></List1>
806                                         <List1 Include=""gb_d.txt""><Culture>gb</Culture></List1>
807
808                                         <List2 Include=""fr_x.txt""><Culture>fr</Culture></List2>
809                                         <List2 Include=""gb_z.txt""><Culture>gb</Culture></List2>
810
811                                         <Foo Include=""1_a1""><Md>1</Md></Foo>
812                                         <Foo Include=""2_b1""><Md>2</Md></Foo>
813                                         <Foo Include=""1_c1""><Md>1</Md></Foo>
814                                 </ItemGroup>
815
816                                 <Target Name=""foo"" Inputs=""@(List1);@(List2)"" Outputs=""%(Culture).foo"">
817                                         <Message Text=""TargetStarted"" />
818                                         <Message Text=""List1: @(List1), List2: @(List2)""/>
819                                 </Target>
820                         </Project>";
821
822                         Engine engine = new Engine (Consts.BinPath);
823                         Project project = engine.CreateNewProject ();
824
825                         TestMessageLogger testLogger = new TestMessageLogger ();
826                         engine.RegisterLogger (testLogger);
827
828                         project.LoadXml (projectString);
829                         bool res = project.Build ("foo");
830                         if (!res) {
831                                 testLogger.DumpMessages ();
832                                 Assert.Fail ("A1: Build failed");
833                         }
834
835                         CheckLoggedMessagesInOrder (testLogger, new string [] {
836                                 "TargetStarted",
837                                 "List1: fr_a.txt;fr_c.txt, List2: fr_x.txt",
838
839                                 "TargetStarted",
840                                 "List1: en_b.txt, List2: ",
841
842                                 "TargetStarted",
843                                 "List1: gb_d.txt, List2: gb_z.txt"
844                         }, "A2");
845                         CheckEngineEventCounts (testLogger, 3, 3, 6, 6);
846                 }
847
848                 void CheckLoggedMessagesInOrder (TestMessageLogger logger, string [] values, string prefix)
849                 {
850                         try {
851                                 for (int i = 0; i < values.Length; i++) {
852                                         logger.CheckLoggedMessageHead (values [i], prefix + "#" + i);
853                                 }
854                                 if (logger.NormalMessageCount > 0)
855                                         Assert.Fail ("{0}: Expected {1} messages, but found {2}",
856                                                 prefix, values.Length, values.Length + logger.NormalMessageCount);
857                         } catch (NUnit.Framework.AssertionException) {
858                                 logger.DumpMessages ();
859                                 throw;
860                         }
861                 }
862
863                 void CheckMessage (TestMessageLogger logger, string culture, string items, string id)
864                 {
865                         logger.CheckLoggedMessageHead (String.Format ("Culture: {0} -- ResXFile: {1}", culture, items), id);
866                 }
867
868                 void CheckMessage2 (TestMessageLogger logger, string culture, string resx_files, string nonresx_files, string id)
869                 {
870                         logger.CheckLoggedMessageHead (String.Format ("Culture: {0} -- ResXFiles: {1} NonResXFiles: {2}", culture, resx_files, nonresx_files), id);
871                 }
872
873                 void CheckLoggedMessageAny (TestMessageLogger logger, string expected, string id)
874                 {
875                         if (logger.CheckAny (expected, MessageImportance.Normal) == 1)
876                                 Assert.Fail ("{0}: Expected message '{1}' was not emitted.", id, expected);
877                 }
878
879                 void CheckEngineEventCounts (TestMessageLogger logger, int target_start, int target_finish, int task_start, int task_finish)
880                 {
881                         Assert.AreEqual (target_start, logger.TargetStarted, "TargetStarted event count doesn't match");
882                         Assert.AreEqual (target_finish, logger.TargetFinished, "TargetFinished event count doesn't match");
883                         Assert.AreEqual (task_start, logger.TaskStarted, "TaskStarted event count doesn't match");
884                         Assert.AreEqual (task_finish, logger.TaskFinished, "TaskFinished event count doesn't match");
885                 }
886         }
887 }