65b01a82b79ffacd8eb670f1a02d3959f6e5132a
[mono.git] / mcs / class / Microsoft.Build.Engine / Test / Microsoft.Build.BuildEngine / TargetTest.cs
1 //
2 // TargetTest.cs
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //
7 // (C) 2006 Marek Sieradzki
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;
30 using Microsoft.Build.BuildEngine;
31 using Microsoft.Build.Framework;
32 using Microsoft.Build.Utilities;
33 using NUnit.Framework;
34 using System.IO;
35
36 namespace MonoTests.Microsoft.Build.BuildEngine {
37         [TestFixture]
38         public class TargetTest {
39                 
40                 Engine                  engine;
41                 Project                 project;
42                 
43                 [Test]
44                 public void TestFromXml1 ()
45                 {
46                         string documentString = @"
47                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
48                                         <Target Name='Target'>
49                                         </Target>
50                                 </Project>
51                         ";
52
53                         engine = new Engine (Consts.BinPath);
54
55                         project = engine.CreateNewProject ();
56                         project.LoadXml (documentString);
57
58                         Target[] t = new Target [1];
59                         project.Targets.CopyTo (t, 0);
60
61                         Assert.AreEqual (String.Empty, t [0].Condition, "A1");
62                         Assert.AreEqual (String.Empty, t [0].DependsOnTargets, "A2");
63                         Assert.IsFalse (t [0].IsImported, "A3");
64                         Assert.AreEqual ("Target", t [0].Name, "A4");
65                 }
66
67                 [Test]
68                 public void TestFromXml2 ()
69                 {
70                         string documentString = @"
71                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
72                                         <Target Name='Target' Condition='false' DependsOnTargets='X' >
73                                         </Target>
74                                 </Project>
75                         ";
76
77                         engine = new Engine (Consts.BinPath);
78
79                         project = engine.CreateNewProject ();
80                         project.LoadXml (documentString);
81
82                         Target[] t = new Target [1];
83                         project.Targets.CopyTo (t, 0);
84
85                         Assert.AreEqual ("false", t [0].Condition, "A1");
86                         Assert.AreEqual ("X", t [0].DependsOnTargets, "A2");
87
88                         t [0].Condition = "true";
89                         t [0].DependsOnTargets = "A;B";
90
91                         Assert.AreEqual ("true", t [0].Condition, "A3");
92                         Assert.AreEqual ("A;B", t [0].DependsOnTargets, "A4");
93                 }
94
95                 [Test]
96                 public void TestAddNewTask1 ()
97                 {
98                         string documentString = @"
99                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
100                                         <Target Name='Target' >
101                                         </Target>
102                                 </Project>
103                         ";
104
105                         engine = new Engine (Consts.BinPath);
106
107                         project = engine.CreateNewProject ();
108                         project.LoadXml (documentString);
109
110                         Target[] t = new Target [1];
111                         project.Targets.CopyTo (t, 0);
112
113                         BuildTask bt = t [0].AddNewTask ("Message");
114
115                         Assert.AreEqual ("Message", bt.Name, "A1");
116                 }
117
118                 [Test]
119                 [ExpectedException (typeof (ArgumentNullException))]
120                 public void TestAddNewTask2 ()
121                 {
122                         string documentString = @"
123                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
124                                         <Target Name='Target' >
125                                         </Target>
126                                 </Project>
127                         ";
128
129                         engine = new Engine (Consts.BinPath);
130
131                         project = engine.CreateNewProject ();
132                         project.LoadXml (documentString);
133
134                         Target[] t = new Target [1];
135                         project.Targets.CopyTo (t, 0);
136
137                         t [0].AddNewTask (null);
138                 }
139
140                 [Test]
141                 public void TestGetEnumerator ()
142                 {
143                         string documentString = @"
144                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
145                                         <Target Name='Target' >
146                                                 <Message Text='text' />
147                                                 <Warning Text='text' />
148                                         </Target>
149                                 </Project>
150                         ";
151
152                         engine = new Engine (Consts.BinPath);
153
154                         project = engine.CreateNewProject ();
155                         project.LoadXml (documentString);
156
157                         Target[] t = new Target [1];
158                         project.Targets.CopyTo (t, 0);
159
160                         IEnumerator e = t [0].GetEnumerator ();
161                         e.MoveNext ();
162                         Assert.AreEqual ("Message", ((BuildTask) e.Current).Name, "A1");
163                         e.MoveNext ();
164                         Assert.AreEqual ("Warning", ((BuildTask) e.Current).Name, "A2");
165                         Assert.IsFalse (e.MoveNext (), "A3");
166                 }
167
168                 [Test]
169                 [ExpectedException (typeof (InvalidProjectFileException))]
170                 public void TestOnError1 ()
171                 {
172                         Engine engine;
173                         Project project;
174
175                         string documentString = @"
176                                 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
177                                         <Target Name='A'>
178                                                 <OnError ExecuteTargets='B' />
179                                                 <Error Text='text' />
180                                         </Target>
181                                 </Project>
182                         ";
183
184                         engine = new Engine (Consts.BinPath);
185                         project = engine.CreateNewProject ();
186                         project.LoadXml (documentString);
187                 }
188
189                 [Test]
190                 public void TestRemoveTask1 ()
191                 {
192                         string documentString = @"
193                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
194                                         <Target Name='Target' >
195                                                 <Message Text='text' />
196                                                 <Warning Text='text' />
197                                         </Target>
198                                 </Project>
199                         ";
200
201                         engine = new Engine (Consts.BinPath);
202
203                         project = engine.CreateNewProject ();
204                         project.LoadXml (documentString);
205
206                         Target[] t = new Target [1];
207                         project.Targets.CopyTo (t, 0);
208
209                         IEnumerator e = t [0].GetEnumerator ();
210                         e.MoveNext ();
211                         t [0].RemoveTask ((BuildTask) e.Current);
212                         e = t [0].GetEnumerator ();
213                         e.MoveNext ();
214                         Assert.AreEqual ("Warning", ((BuildTask) e.Current).Name, "A1");
215                         Assert.IsFalse (e.MoveNext (), "A2");
216                 }
217
218                 [Test]
219                 [ExpectedException (typeof (ArgumentNullException))]
220                 public void TestRemoveTask2 ()
221                 {
222                         string documentString = @"
223                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
224                                         <Target Name='Target' >
225                                         </Target>
226                                 </Project>
227                         ";
228
229                         engine = new Engine (Consts.BinPath);
230
231                         project = engine.CreateNewProject ();
232                         project.LoadXml (documentString);
233
234                         Target[] t = new Target [1];
235                         project.Targets.CopyTo (t, 0);
236                         t [0].RemoveTask (null);
237                 }
238
239                 [Test]
240                 public void TestTargetOutputs1 ()
241                 {
242                         Engine engine;
243                         Project project;
244
245                         string documentString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
246                         <ItemGroup>
247                                 <fruit Include=""apple""/>
248                                 <fruit Include=""rhubarb""/>
249                                 <fruit Include=""apricot""/>
250                         </ItemGroup>
251
252                         <Target Name=""Main"">
253                                 <CallTarget Targets=""foo"">
254                                         <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
255                                 </CallTarget>
256
257                                 <CallTarget Targets=""foo"">
258                                         <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
259                                 </CallTarget>
260                                 <Message Text=""AllOut: @(AllOut)""/>
261                         </Target>
262
263                         <Target Name=""foo"" Outputs=""@(FooItem)"">
264                                 <Message Text=""foo called""/>
265                                 <CreateItem Include=""%(fruit.Identity)"">
266                                         <Output TaskParameter=""Include"" ItemName=""FooItem""/>
267                                 </CreateItem>
268                                 <Message Text=""FooItem: @(FooItem)""/>
269                         </Target>
270                 </Project>";
271
272                         engine = new Engine (Consts.BinPath);
273                         project = engine.CreateNewProject ();
274                         project.LoadXml (documentString);
275
276                         MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
277                                 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
278                         engine.RegisterLogger (logger);
279
280                         bool result = project.Build ("Main");
281                         if (!result) {
282                                 logger.DumpMessages ();
283                                 Assert.Fail ("Build failed");
284                         }
285
286                         try {
287                                 Assert.AreEqual (3, logger.NormalMessageCount, "Expected number of messages");
288                                 logger.CheckLoggedMessageHead ("foo called", "A1");
289                                 logger.CheckLoggedMessageHead ("FooItem: apple;rhubarb;apricot", "A2");
290                                 logger.CheckLoggedMessageHead ("AllOut: apple;rhubarb;apricot;apple;rhubarb;apricot", "A3");
291                                 Assert.AreEqual (0, logger.NormalMessageCount, "Extra messages found");
292
293                                 Assert.AreEqual (2, logger.TargetStarted, "TargetStarted count");
294                                 Assert.AreEqual (2, logger.TargetFinished, "TargetFinished count");
295                                 Assert.AreEqual (8, logger.TaskStarted, "TaskStarted count");
296                                 Assert.AreEqual (8, logger.TaskFinished, "TaskFinished count");
297
298                         } catch (AssertionException) {
299                                 logger.DumpMessages ();
300                                 throw;
301                         }
302                 }
303
304                 [Test]
305                 public void TestTargetOutputsIncludingMetadata ()
306                 {
307                         Engine engine;
308                         Project project;
309
310                         string documentString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
311                         <ItemGroup>
312                                 <fruit Include=""apple""><md>a</md></fruit>
313                                 <fruit Include=""rhubarb""><md>b</md></fruit>
314                                 <fruit Include=""apricot""><md>c</md></fruit>
315                         </ItemGroup>
316
317                         <Target Name=""Main"">
318                                 <CallTarget Targets=""foo"">
319                                         <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
320                                 </CallTarget>
321
322                                 <CallTarget Targets=""foo"">
323                                         <Output TaskParameter=""TargetOutputs"" ItemName=""AllOut""/>
324                                 </CallTarget>
325                                 <Message Text=""AllOut: @(AllOut) metadata: %(AllOut.md)""/>
326                         </Target>
327
328                         <Target Name=""foo"" Outputs=""@(FooItem)"">
329                                 <Message Text=""foo called""/>
330                                 <CreateItem Include=""@(fruit)"">
331                                         <Output TaskParameter=""Include"" ItemName=""FooItem""/>
332                                 </CreateItem>
333                                 <Message Text=""FooItem: @(FooItem) metadata: %(FooItem.md)""/>
334                         </Target>
335                 </Project>";
336
337                         engine = new Engine (Consts.BinPath);
338                         project = engine.CreateNewProject ();
339                         project.LoadXml (documentString);
340
341                         MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
342                                 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
343                         engine.RegisterLogger (logger);
344
345                         bool result = project.Build ("Main");
346                         if (!result) {
347                                 logger.DumpMessages ();
348                                 Assert.Fail ("Build failed");
349                         }
350
351                         try {
352                                 logger.CheckLoggedMessageHead ("foo called", "A1");
353                                 logger.CheckLoggedMessageHead ("FooItem: apple metadata: a", "A2");
354                                 logger.CheckLoggedMessageHead ("FooItem: rhubarb metadata: b", "A3");
355                                 logger.CheckLoggedMessageHead ("FooItem: apricot metadata: c", "A4");
356
357                                 logger.CheckLoggedMessageHead ("AllOut: apple;apple metadata: a", "A5");
358                                 logger.CheckLoggedMessageHead ("AllOut: rhubarb;rhubarb metadata: b", "A6");
359                                 logger.CheckLoggedMessageHead ("AllOut: apricot;apricot metadata: c", "A7");
360
361                                 Assert.AreEqual (0, logger.NormalMessageCount, "Extra messages found");
362
363                                 Assert.AreEqual (2, logger.TargetStarted, "TargetStarted count");
364                                 Assert.AreEqual (2, logger.TargetFinished, "TargetFinished count");
365                                 Assert.AreEqual (10, logger.TaskStarted, "TaskStarted count");
366                                 Assert.AreEqual (10, logger.TaskFinished, "TaskFinished count");
367
368                         } catch (AssertionException) {
369                                 logger.DumpMessages ();
370                                 throw;
371                         }
372                 }
373
374                 [Test]
375                 public void TestOverridingTargets ()
376                 {
377                         Engine engine;
378                         Project project;
379
380                         string second = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
381                                 <Target Name='BeforeBuild'/>
382                                 <Target Name='AfterBuild'/>
383                                 <Target Name='Build' DependsOnTargets='BeforeBuild'>
384                                         <Message Text='Build executing'/>
385                                         <CallTarget Targets='AfterBuild'/>
386                                 </Target>
387                 </Project>";
388                         using (StreamWriter sw = new StreamWriter (Path.Combine ("Test", Path.Combine ("resources", "second.proj")))) {
389                                 sw.Write (second);
390                         }
391
392                         string documentString = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
393                                 <Target Name='AfterBuild'>
394                                         <Message Text='Overriding AfterBuild'/>
395                                 </Target>
396
397                                 <Import Project='Test/resources/second.proj'/>
398                                 <Target Name='BeforeBuild'>
399                                         <Message Text='Overriding BeforeBuild'/>
400                                 </Target>
401                 </Project>";
402
403                         engine = new Engine (Consts.BinPath);
404                         project = engine.CreateNewProject ();
405                         project.LoadXml (documentString);
406
407                         MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
408                                 new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
409                         engine.RegisterLogger (logger);
410
411                         bool result = project.Build ("Build");
412                         if (!result) {
413                                 logger.DumpMessages ();
414                                 Assert.Fail ("Build failed");
415                         }
416
417                         logger.CheckLoggedMessageHead ("Overriding BeforeBuild", "A1");
418                         logger.CheckLoggedMessageHead ("Build executing", "A1");
419
420                         Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
421                 }
422
423         }
424 }