Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / Microsoft.Build / Test / Microsoft.Build.Evaluation / ProjectTest.cs
1 //
2 // ProjectTest.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.Evaluation;
34 using NUnit.Framework;
35 using Microsoft.Build.Exceptions;
36 using Microsoft.Build.Logging;
37 using Microsoft.Build.Framework;
38 using System.Collections.Generic;
39
40 namespace MonoTests.Microsoft.Build.Evaluation
41 {
42         [TestFixture]
43         public class ProjectTest
44         {
45                 [Test]
46                 public void EscapeDoesWTF ()
47                 {
48                         string value_xml = "What are 'ESCAPE' & \"EVALUATE\" ? $ # % ^";
49                         string value = "What are 'ESCAPE' & \"EVALUATE\" ? $ # % ^";
50                         string escaped = "What are %27ESCAPE%27 & \"EVALUATE\" %3f %24 # %25 ^";
51                         string xml = string.Format (@"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
52         <PropertyGroup>
53                 <Foo>{0}</Foo>
54                 <Baz>$(FOO)</Baz>
55         </PropertyGroup>
56 </Project>", value_xml);
57                         var path = "file://localhost/foo.xml";
58                         var reader = XmlReader.Create (new StringReader (xml), null, path);
59                         var root = ProjectRootElement.Create (reader);
60                         var proj = new Project (root);
61                         var prop = proj.Properties.First (p => p.Name == "Foo");
62                         Assert.AreEqual (value, prop.UnevaluatedValue, "#1");
63                         Assert.AreEqual (value, prop.EvaluatedValue, "#2");
64                         // eh?
65                         Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#3");
66                         prop = proj.Properties.First (p => p.Name == "Baz");
67                         Assert.AreEqual ("$(FOO)", prop.UnevaluatedValue, "#4");
68                         Assert.AreEqual (value, prop.EvaluatedValue, "#5");
69                         // eh?
70                         Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#6");
71                         
72                         // OK you are fine.
73                         Assert.AreEqual (escaped, ProjectCollection.Escape (value), "#7");
74                 }
75                 
76                 [Test]
77                 public void FullPath ()
78                 {
79                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
80                         var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
81                         var root = ProjectRootElement.Create (xml);
82                         var proj = new Project (root);
83                         proj.FullPath = "ABC";
84                         Assert.IsTrue (proj.FullPath.EndsWith (Path.DirectorySeparatorChar + "ABC"), "#1");
85                         Assert.AreEqual (root.FullPath, proj.FullPath, "#2");
86                 }
87                 
88                 [Test]
89                 public void BuildEmptyProject ()
90                 {
91                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
92                         var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
93                         var root = ProjectRootElement.Create (xml);
94                         root.FullPath = "ProjectTest.BuildEmptyProject.proj";
95             
96                         // This seems to do nothing and still returns true
97                         Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.1.proj" }.Build (), "#1");
98                         // This seems to fail to find the appropriate target
99                         Assert.IsFalse (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.2.proj" }.Build ("Build", null), "#2");
100                         // Thus, this tries to build all the targets (empty) and no one failed, so returns true(!)
101                         Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.3.proj" }.Build (new string [0], null), "#3");
102                         // Actially null "targets" is accepted and returns true(!!)
103                         Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.4.proj" }.Build ((string []) null, null), "#4");
104                         // matching seems to be blindly done, null string also results in true(!!)
105                         Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.5.proj" }.Build ((string) null, null), "#5");
106                 }
107                 
108                 [Test]
109                 [ExpectedException (typeof (InvalidProjectFileException))]
110                 public void LoadInvalidProjectForBadCondition ()
111                 {
112                         string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
113   <PropertyGroup>
114     <Foo>What are 'ESCAPE' &amp; ""EVALUATE"" ? $ # % ^</Foo>
115     <!-- Note that this contains invalid Condition expression, yet ProjectElement.Create() does NOT fail. -->
116     <Baz Condition=""$(Void)=="">$(FOO)</Baz>
117   </PropertyGroup>
118 </Project>";
119                         var reader = XmlReader.Create (new StringReader (xml));
120                         var root = ProjectRootElement.Create (reader);
121                         new Project (root);
122                 }
123                 
124                 [Test]
125                 public void ExpandString ()
126                 {
127                         string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
128   <PropertyGroup>
129     <Foo>What are 'ESCAPE' &amp; ""EVALUATE"" ? $ # % ^</Foo>
130     <Bar>y</Bar>
131     <Baz Condition=""$(Void)==''"">$(FOO)</Baz>
132   </PropertyGroup>
133 </Project>";
134                         var reader = XmlReader.Create (new StringReader (xml));
135                         var root = ProjectRootElement.Create (reader);
136                         var proj = new Project (root);
137                         root.FullPath = "ProjectTest.ExpandString.proj";
138                         Assert.AreEqual ("xyz", proj.ExpandString ("x$(BAR)z"), "#1");
139                         Assert.AreEqual ("x$(BARz", proj.ExpandString ("x$(BARz"), "#2"); // incomplete
140                         Assert.AreEqual ("xz", proj.ExpandString ("x@(BAR)z"), "#3"); // not an item
141                 }
142                 
143                 [Test]
144                 public void BuildCSharpTargetGetFrameworkPaths ()
145                 {
146             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
147   <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
148 </Project>";
149             var xml = XmlReader.Create (new StringReader (project_xml));
150             var root = ProjectRootElement.Create (xml);
151             var proj = new Project (root);
152                         root.FullPath = "ProjectTest.BuildCSharpTargetGetFrameworkPaths.proj";
153                         Assert.IsTrue (proj.Build ("GetFrameworkPaths", new ILogger [] {/*new ConsoleLogger ()*/}));
154                 }
155                 
156                 [Test]
157                 public void ProperiesMustBeDistinct ()
158                 {
159             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
160   <PropertyGroup>
161     <AssemblyName>Foo</AssemblyName>
162     <OutputPath>Test</OutputPath>
163   </PropertyGroup>
164 </Project>";
165             var xml = XmlReader.Create (new StringReader (project_xml));
166             var root = ProjectRootElement.Create (xml);
167                         root.FullPath = "ProjectTest.BuildCSharpTargetBuild.proj";
168                         var proj = new Project (root);
169                         var list = new List<ProjectProperty> ();
170                         foreach (var p in proj.Properties)
171                                 if (list.Any (pp => pp.Name.Equals (p.Name, StringComparison.OrdinalIgnoreCase)))
172                                         Assert.Fail ("Property " + p.Name + " already exists.");
173                 }
174                 
175                 [Test]
176                 public void BuildCSharpTargetBuild ()
177                 {
178             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
179   <PropertyGroup>
180     <AssemblyName>Foo</AssemblyName>
181   </PropertyGroup>
182   <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
183 </Project>";
184             var xml = XmlReader.Create (new StringReader (project_xml));
185             var root = ProjectRootElement.Create (xml);
186                         root.FullPath = "ProjectTest.BuildCSharpTargetBuild.proj";
187                         var proj = new Project (root, null, "4.0");
188                         Assert.IsFalse (proj.Build ("Build", new ILogger [] {/*new ConsoleLogger (LoggerVerbosity.Diagnostic)*/})); // missing mandatory properties
189                 }
190                 
191                 [Test]
192                 public void EvaluateItemConditionThenIgnored ()
193                 {
194             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
195   <PropertyGroup>
196     <P></P>
197   </PropertyGroup>
198   <ItemGroup>
199     <Foo Condition='' Include='x' />
200     <Bar Include='$(P)' />
201     <Baz Include='z' />
202   </ItemGroup>
203 </Project>";
204                         var xml = XmlReader.Create (new StringReader (project_xml));
205                         var root = ProjectRootElement.Create (xml);
206                         var proj = new Project (root);
207                         // note that Foo is ignored BUT Bar is NOT ignored.
208                         Assert.AreEqual (2, proj.ItemsIgnoringCondition.Count, "#1");
209                         Assert.IsNotNull ("Bar", proj.ItemsIgnoringCondition.First ().ItemType, "#2");
210                         Assert.IsNotNull ("Baz", proj.ItemsIgnoringCondition.Last ().ItemType, "#3");
211                 }
212                 
213                 [Test]
214                 public void EvaluateSamePropertiesInOrder ()
215                 {
216                         // used in Microsoft.Common.targets
217             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
218   <PropertyGroup>
219     <BaseIntermediateOutputPath Condition=""'$(BaseIntermediateOutputPath)' == ''"">obj\</BaseIntermediateOutputPath>
220   </PropertyGroup>
221 </Project>";
222                         var xml = XmlReader.Create (new StringReader (project_xml));
223                         var root = ProjectRootElement.Create (xml);
224                         var proj = new Project (root);
225                         Assert.AreEqual ("obj\\", proj.GetPropertyValue ("BaseIntermediateOutputPath"), "#1");
226                 }
227                 
228                 [Test]
229                 public void DirtyMarking ()
230                 {
231                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
232                         var xml = XmlReader.Create (new StringReader (project_xml));
233                         var root = ProjectRootElement.Create (xml);
234                         var proj = new Project (root);
235                         Assert.IsFalse (proj.IsDirty, "#1");
236                         proj.MarkDirty ();
237                         Assert.IsTrue (proj.IsDirty, "#2");
238                 }
239                 
240                 [Test]
241                 public void DirtyMarking2 ()
242                 {
243                         string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
244                         var xml = XmlReader.Create (new StringReader (project_xml));
245                         var root = ProjectRootElement.Create (xml);
246                         var proj = new Project (root);
247                         proj.DisableMarkDirty = true;
248                         proj.MarkDirty ();
249                         Assert.IsFalse (proj.IsDirty, "#1"); // not rejected, just ignored.
250                         proj.DisableMarkDirty = false;
251                         Assert.IsFalse (proj.IsDirty, "#2"); // not like status pending
252                         proj.MarkDirty ();
253                         Assert.IsTrue (proj.IsDirty, "#3");
254                 }
255                 
256                 [Test]
257                 public void CreateProjectInstance ()
258                 {
259             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
260   <PropertyGroup>
261     <AssemblyName>Foo</AssemblyName>
262   </PropertyGroup>
263   <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
264 </Project>";
265             var xml = XmlReader.Create (new StringReader (project_xml));
266             var root = ProjectRootElement.Create (xml);
267                         var proj = new Project (root, null, "4.0");
268                         var inst = proj.CreateProjectInstance ();
269                         Assert.AreEqual ("4.0", inst.ToolsVersion, "#1");
270                 }
271                 
272                 [Test]
273                 public void LoadCaseInsensitive ()
274                 {
275             string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
276   <PropertyGroup>
277     <AssemblyName>Foo</AssemblyName>
278   </PropertyGroup>
279   <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.Targets' />
280 </Project>";
281             var xml = XmlReader.Create (new StringReader (project_xml));
282             var root = ProjectRootElement.Create (xml);
283                         new Project (root, null, "4.0");
284                 }
285         }
286 }
287