5 // Atsushi Enomoto (atsushi@xamarin.com)
7 // Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
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;
40 namespace MonoTests.Microsoft.Build.Evaluation
43 public class ProjectTest
46 public void EscapeDoesWTF ()
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'>
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");
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");
70 Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#6");
73 Assert.AreEqual (escaped, ProjectCollection.Escape (value), "#7");
77 public void FullPath ()
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");
89 public void BuildEmptyProject ()
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";
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");
109 [ExpectedException (typeof (InvalidProjectFileException))]
110 public void LoadInvalidProjectForBadCondition ()
112 string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
114 <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo>
115 <!-- Note that this contains invalid Condition expression, yet ProjectElement.Create() does NOT fail. -->
116 <Baz Condition=""$(Void)=="">$(FOO)</Baz>
119 var reader = XmlReader.Create (new StringReader (xml));
120 var root = ProjectRootElement.Create (reader);
125 public void ExpandString ()
127 string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
129 <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo>
131 <Baz Condition=""$(Void)==''"">$(FOO)</Baz>
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
144 public void BuildCSharpTargetGetFrameworkPaths ()
146 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
147 <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
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 ()*/}));
157 public void ProperiesMustBeDistinct ()
159 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
161 <AssemblyName>Foo</AssemblyName>
162 <OutputPath>Test</OutputPath>
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.");
176 public void BuildCSharpTargetBuild ()
178 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
180 <AssemblyName>Foo</AssemblyName>
182 <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
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
192 public void EvaluateItemConditionThenIgnored ()
194 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
199 <Foo Condition='' Include='x' />
200 <Bar Include='$(P)' />
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");
214 public void EvaluateSamePropertiesInOrder ()
216 // used in Microsoft.Common.targets
217 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
219 <BaseIntermediateOutputPath Condition=""'$(BaseIntermediateOutputPath)' == ''"">obj\</BaseIntermediateOutputPath>
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");
229 public void DirtyMarking ()
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");
237 Assert.IsTrue (proj.IsDirty, "#2");
241 public void DirtyMarking2 ()
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;
249 Assert.IsFalse (proj.IsDirty, "#1"); // not rejected, just ignored.
250 proj.DisableMarkDirty = false;
251 Assert.IsFalse (proj.IsDirty, "#2"); // not like status pending
253 Assert.IsTrue (proj.IsDirty, "#3");
257 public void CreateProjectInstance ()
259 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
261 <AssemblyName>Foo</AssemblyName>
263 <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
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");
273 public void LoadCaseInsensitive ()
275 string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
277 <AssemblyName>Foo</AssemblyName>
279 <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.Targets' />
281 var xml = XmlReader.Create (new StringReader (project_xml));
282 var root = ProjectRootElement.Create (xml);
283 new Project (root, null, "4.0");