Changed UploadStringAsync to handle UploadString encapsulated exceptions.
[mono.git] / mcs / class / Microsoft.Build / Test / Microsoft.Build.Execution / ProjectInstanceTest.cs
1 //
2 // ProjectInstanceTest.cs
3 //
4 // Author:
5 //   Atsushi Enomoto (atsushi@xamarin.com)
6 //
7 // Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.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.IO;
30 using System.Linq;
31 using System.Xml;
32 using Microsoft.Build.Construction;
33 using Microsoft.Build.Execution;
34 using NUnit.Framework;
35 using Microsoft.Build.Evaluation;
36 using Microsoft.Build.Utilities;
37 using Microsoft.Build.Framework;
38 using Microsoft.Build.Logging;
39
40 namespace MonoTests.Microsoft.Build.Execution
41 {
42         [TestFixture]
43         public class ProjectInstanceTest
44         {
45                 [Test]
46                 public void ItemsAndProperties ()
47                 {
48             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
49   <ItemGroup>
50     <X Condition='false' Include='bar.txt' />
51     <X Include='foo.txt'>
52       <M>m</M>
53       <N>=</N>
54     </X>
55   </ItemGroup>
56   <PropertyGroup>
57     <P Condition='false'>void</P>
58     <P Condition='true'>valid</P>
59   </PropertyGroup>
60 </Project>";
61             var xml = XmlReader.Create (new StringReader(project_xml));
62             var root = ProjectRootElement.Create (xml);
63             var proj = new ProjectInstance (root);
64             var item = proj.Items.First ();
65                         Assert.AreEqual ("foo.txt", item.EvaluatedInclude, "#1");
66                         var prop = proj.Properties.First (p => p.Name=="P");
67                         Assert.AreEqual ("valid", prop.EvaluatedValue, "#2");
68                         Assert.IsNotNull (proj.GetProperty ("MSBuildProjectDirectory"), "#3");
69                         Assert.AreEqual ("2.0", proj.ToolsVersion, "#4");
70                 }
71                 
72                 [Test]
73                 public void ExplicitToolsVersion ()
74                 {
75             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
76             var xml = XmlReader.Create (new StringReader(project_xml));
77             var root = ProjectRootElement.Create (xml);
78                         var proj = new ProjectInstance (root, null, "4.0", new ProjectCollection ());
79                         Assert.AreEqual ("4.0", proj.ToolsVersion, "#1");
80                 }
81                 
82                 [Test]
83                 public void BuildEmptyProject ()
84                 {
85                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
86                         var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
87                         var root = ProjectRootElement.Create (xml);
88                         // This seems to do nothing and still returns true
89                         root.FullPath = "ProjectInstanceTest.BuildEmptyProject.1.proj";
90                         Assert.IsTrue (new ProjectInstance (root).Build (), "#1");
91                         // This seems to fail to find the appropriate target
92                         root.FullPath = "ProjectInstanceTest.BuildEmptyProject.2.proj";
93                         Assert.IsFalse (new ProjectInstance (root).Build ("Build", null), "#2");
94                         // Thus, this tries to build all the targets (empty) and no one failed, so returns true(!)
95                         root.FullPath = "ProjectInstanceTest.BuildEmptyProject.3.proj";
96                         Assert.IsTrue (new ProjectInstance (root).Build (new string [0], null), "#3");
97                         // Actially null "targets" is accepted and returns true(!!)
98                         root.FullPath = "ProjectInstanceTest.BuildEmptyProject.4.proj";
99                         Assert.IsTrue (new ProjectInstance (root).Build ((string []) null, null), "#4");
100                         // matching seems to be blindly done, null string also results in true(!!)
101                         root.FullPath = "ProjectInstanceTest.BuildEmptyProject.5.proj";
102                         Assert.IsTrue (new ProjectInstance (root).Build ((string) null, null), "#5");
103                 }
104                 
105                 [Test]
106                 public void DefaultTargets ()
107                 {
108                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
109   <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' />
110 </Project>";
111                         var xml = XmlReader.Create (new StringReader(project_xml));
112                         var root = ProjectRootElement.Create (xml);
113                         var proj = new ProjectInstance (root);
114                         Assert.AreEqual (1, proj.DefaultTargets.Count, "#1");
115                         Assert.AreEqual ("Build", proj.DefaultTargets [0], "#2");
116                 }
117                 
118                 [Test]
119                 public void DefaultTargets2 ()
120                 {
121             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
122   <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
123 </Project>";
124             var xml = XmlReader.Create (new StringReader (project_xml));
125             var root = ProjectRootElement.Create (xml);
126                         root.FullPath = "ProjectTest.BuildCSharpTargetBuild.proj";
127                         var proj = new ProjectInstance (root);
128                         Assert.AreEqual (1, proj.DefaultTargets.Count, "#1");
129                         Assert.AreEqual ("Build", proj.DefaultTargets [0], "#2");
130                 }
131                 
132                 [Test]
133                 public void PropertyOverrides ()
134                 {
135             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
136   <PropertyGroup>
137     <X>x</X>
138   </PropertyGroup>
139   <PropertyGroup>
140     <X>y</X>
141   </PropertyGroup>
142 </Project>";
143             var xml = XmlReader.Create (new StringReader (project_xml));
144             var root = ProjectRootElement.Create (xml);
145                         root.FullPath = "ProjectTest.BuildCSharpTargetBuild.proj";
146                         var proj = new ProjectInstance (root);
147                         Assert.AreEqual ("y", proj.GetPropertyValue ("X"), "#1");
148                 }
149                 
150                 [Test]
151                 public void FirstUsingTaskTakesPrecedence1 ()
152                 {
153                         FirstUsingTaskTakesPrecedenceCommon (false, false);
154                 }
155                 
156                 [Test]
157                 public void FirstUsingTaskTakesPrecedence2 ()
158                 {
159                         FirstUsingTaskTakesPrecedenceCommon (true, true);
160                 }
161                 
162                 public void FirstUsingTaskTakesPrecedenceCommon (bool importFirst, bool buildShouldSucceed)
163                 {
164                         string thisAssembly = new Uri (GetType ().Assembly.CodeBase).LocalPath;
165                         string filename = "Test/ProjectTargetInstanceTest.FirstUsingTaskTakesPrecedence.Import.proj";
166                         string imported_xml = string.Format (@"<Project DefaultTargets='Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
167   <UsingTask TaskName='MonoTests.Microsoft.Build.Execution.MyTask' AssemblyFile='{0}' />
168 </Project>", thisAssembly);
169                         string usingTask =  string.Format ("<UsingTask TaskName='MonoTests.Microsoft.Build.Execution.SubNamespace.MyTask' AssemblyFile='{0}' />", thisAssembly);
170                         string import = string.Format ("<Import Project='{0}' />", filename);
171                         string project_xml = string.Format (@"<Project DefaultTargets='Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
172                         {0}
173                         {1}
174   <Target Name='Foo'>
175     <MyTask />
176   </Target>
177 </Project>", 
178                                 importFirst ? import : usingTask, importFirst ? usingTask : import);
179                         try {
180                                 File.WriteAllText (filename, imported_xml);
181                                 var xml = XmlReader.Create (new StringReader (project_xml));
182                                 var root = ProjectRootElement.Create (xml);
183                                 Assert.IsTrue (root.UsingTasks.All (u => !string.IsNullOrEmpty (u.AssemblyFile)), "#1");
184                                 Assert.IsTrue (root.UsingTasks.All (u => string.IsNullOrEmpty (u.AssemblyName)), "#2");
185                                 root.FullPath = "ProjectTargetInstanceTest.FirstUsingTaskTakesPrecedence.proj";
186                                 var proj = new ProjectInstance (root);
187                                 Assert.AreEqual (buildShouldSucceed, proj.Build (), "#3");
188                         } finally {
189                                 File.Delete (filename);
190                         }
191                 }
192                 
193                 [Test]
194                 public void MissingTypeForUsingTaskStillWorks ()
195                 {
196                         string thisAssembly = new Uri (GetType ().Assembly.CodeBase).LocalPath;
197                         string project_xml = string.Format (@"<Project DefaultTargets='X' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
198   <UsingTask AssemblyFile='{0}' TaskName='NonExistent' />
199   <Target Name='X' />
200 </Project>", thisAssembly);
201                         var xml = XmlReader.Create (new StringReader (project_xml));
202                         var root = ProjectRootElement.Create (xml);
203                         root.FullPath = "ProjectInstanceTest.MissingTypeForUsingTaskStillWorks.proj";
204                         var proj = new ProjectInstance (root);
205                         Assert.IsTrue (proj.Build (), "#1");
206                 }
207                 
208                 [Test]
209                 public void MissingTypeForUsingTaskStillWorks2 ()
210                 {
211                         string thisAssembly = new Uri (GetType ().Assembly.CodeBase).LocalPath;
212                         string project_xml = @"<Project DefaultTargets='X' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
213   <UsingTask AssemblyFile='nonexistent.dll' TaskName='NonExistent' />
214   <Target Name='X' />
215 </Project>";
216             var xml = XmlReader.Create (new StringReader (project_xml));
217             var root = ProjectRootElement.Create (xml);
218                         root.FullPath = "ProjectInstanceTest.MissingTypeForUsingTaskStillWorks2.proj";
219                         var proj = new ProjectInstance (root);
220                         Assert.IsTrue (proj.Build (), "#1");
221                 }
222
223                 [Test]
224                 public void ExpandStringWithMetadata ()
225                 {
226                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
227   <ItemGroup>
228     <Foo Include='xxx'><M>x</M></Foo>
229     <Foo Include='yyy'><M>y</M></Foo>
230   </ItemGroup>
231 </Project>";
232                         var xml = XmlReader.Create (new StringReader (project_xml));
233                         var root = ProjectRootElement.Create (xml);
234                         root.FullPath = "ProjectInstanceTest.ExpandStringWithMetadata.proj";
235                         var proj = new ProjectInstance (root);
236                         Assert.AreEqual ("xxx;yyy", proj.ExpandString ("@(FOO)"), "#1"); // so, metadata is gone...
237                 }
238
239                 [Test]
240                 public void EvaluatePropertyWithQuotation ()
241                 {
242                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
243   <ItemGroup>
244     <Foo Include='abc/xxx.txt' />
245   </ItemGroup>
246   <PropertyGroup>
247     <B>foobar</B>
248   </PropertyGroup>
249   <Target Name='default'>
250     <CreateProperty Value=""@(Foo->'%(Filename)%(Extension)')"">
251       <Output TaskParameter='Value' PropertyName='P' />
252     </CreateProperty>
253     <CreateProperty Value='$(B)|$(P)'>
254       <Output TaskParameter='Value' PropertyName='Q' />
255     </CreateProperty>
256   </Target>
257 </Project>";
258                         var xml = XmlReader.Create (new StringReader (project_xml));
259                         var root = ProjectRootElement.Create (xml);
260                         root.FullPath = "ProjectInstanceTest.EvaluatePropertyWithQuotation.proj";
261                         var proj = new ProjectInstance (root);
262                         proj.Build ();
263                         var p = proj.GetProperty ("P");
264                         Assert.AreEqual ("xxx.txt", p.EvaluatedValue, "#1");
265                         var q = proj.GetProperty ("Q");
266                         Assert.AreEqual ("foobar|xxx.txt", q.EvaluatedValue, "#2");
267                 }
268
269                 [Test]
270                 public void Choose ()
271                 {
272                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
273   <Choose>
274     <When Condition="" '$(DebugSymbols)' != '' "">
275       <PropertyGroup>
276         <DebugXXX>True</DebugXXX>
277       </PropertyGroup>
278     </When>
279     <Otherwise>
280       <PropertyGroup>
281         <DebugXXX>False</DebugXXX>
282       </PropertyGroup>
283     </Otherwise>
284   </Choose>
285 </Project>";
286                         var xml = XmlReader.Create (new StringReader (project_xml));
287                         var root = ProjectRootElement.Create (xml);
288                         root.FullPath = "ProjectInstanceTest.Choose.proj";
289                         var proj = new ProjectInstance (root);
290                         var p = proj.GetProperty ("DebugXXX");
291                         Assert.IsNotNull (p, "#1");
292                         Assert.AreEqual ("False", p.EvaluatedValue, "#2");
293                 }
294         }
295         
296         namespace SubNamespace
297         {
298                 public class MyTask : Task
299                 {
300                         public override bool Execute ()
301                         {
302                                 return false;
303                         }
304                 }
305         }
306                 
307         public class MyTask : Task
308         {
309                 public override bool Execute ()
310                 {
311                         return true;
312                 }
313         }
314 }
315