diff options
author | Jo Shields <directhex@apebox.org> | 2014-02-19 22:12:43 +0000 |
---|---|---|
committer | Jo Shields <directhex@apebox.org> | 2014-02-19 22:12:43 +0000 |
commit | 9972bf87b4f27d9c8f358ef8414ac1ab957a2f0f (patch) | |
tree | 5bb230c1d698659115f918e243c1d4b0aa4c7f51 /mcs/class/Microsoft.Build/Test | |
parent | d0a215f5626219ff7927f576588a777e5331c7be (diff) | |
download | mono-upstream/3.2.8+dfsg.tar.gz |
Imported Upstream version 3.2.8+dfsgupstream/3.2.8+dfsg
Diffstat (limited to 'mcs/class/Microsoft.Build/Test')
18 files changed, 2520 insertions, 0 deletions
diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectItemElementTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectItemElementTest.cs new file mode 100644 index 0000000000..caa93f1b76 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectItemElementTest.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using NUnit.Framework; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Exceptions; + +namespace MonoTests.Microsoft.Build.Construction +{ + [TestFixture] + public class ProjectItemElementTest + { + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void EmptyInclude () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Include='' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + ProjectRootElement.Create (xml); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void MissingInclude () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + ProjectRootElement.Create (xml); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs new file mode 100644 index 0000000000..e864f4dfb3 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Construction/ProjectRootElementTest.cs @@ -0,0 +1,222 @@ +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using NUnit.Framework; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Exceptions; + +namespace MonoTests.Microsoft.Build.Construction +{ + [TestFixture] + public class ProjectRootElementTest + { + const string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + + [Test] + [ExpectedException (typeof (UriFormatException))] + [Category ("NotWorking")] // URL is constructed for ElementLocation, which we don't support yet. + public void CreateExpectsAbsoluteUri () + { + var xml = XmlReader.Create (new StringReader (empty_project_xml), null, "foo.xml"); + ProjectRootElement.Create (xml); + } + + [Test] + public void CreateAndPaths () + { + Assert.IsNull (ProjectRootElement.Create ().FullPath, "#1"); + var xml = XmlReader.Create (new StringReader (empty_project_xml), null, "file:///foo.xml"); + // This creator does not fill FullPath... + var root = ProjectRootElement.Create (xml); + Assert.IsNull (root.FullPath, "#2"); + Assert.AreEqual (Path.GetDirectoryName (new Uri (GetType ().Assembly.CodeBase).LocalPath), root.DirectoryPath, "#3"); + } + + [Test] + public void FullPathSetter () + { + var root = ProjectRootElement.Create (); + root.FullPath = "test" + Path.DirectorySeparatorChar + "foo.xml"; + var full = Path.Combine (Path.GetDirectoryName (new Uri (GetType ().Assembly.CodeBase).LocalPath), "test", "foo.xml"); + Assert.AreEqual (full, root.FullPath, "#1"); + Assert.AreEqual (Path.GetDirectoryName (full), root.DirectoryPath, "#1"); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void FullPathSetNull () + { + ProjectRootElement.Create ().FullPath = null; + } + + [Test] + public void InvalidProject () + { + try { + ProjectRootElement.Create (XmlReader.Create (new StringReader (" <root/>"))); + Assert.Fail ("should throw InvalidProjectFileException"); + } catch (InvalidProjectFileException ex) { + #if NET_4_5 + Assert.AreEqual (1, ex.LineNumber, "#1"); + // it is very interesting, but unlike XmlReader.LinePosition it returns the position for '<'. + Assert.AreEqual (2, ex.ColumnNumber, "#2"); + #endif + } + } + + [Test] + public void CreateWithXmlLoads () + { + string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><ItemGroup><None Include='bar.txt' /></ItemGroup></Project>"; + var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual (1, root.Items.Count, "#1"); + } + + [Test] + public void ToolsVersionDefault () + { + var g = ProjectCollection.GlobalProjectCollection; + var root = ProjectRootElement.Create (); + // this will be wrong in the future version, but since .NET 4.5 still expects "4.0" we can't say for sure. + Assert.AreEqual ("4.0", root.ToolsVersion, "#1"); + } + + [Test] + public void ToolsVersionIsEmptyWithXml () + { + string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><ItemGroup><None Include='bar.txt' /></ItemGroup></Project>"; + var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual (string.Empty, root.ToolsVersion, "#1"); + } + + [Test] + public void LoadUnknownChild () + { + string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><Unknown /></Project>"; + var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml"); + try { + ProjectRootElement.Create (xml); + Assert.Fail ("should throw InvalidProjectFileException"); + } catch (InvalidProjectFileException ex) { + #if NET_4_5 + Assert.AreEqual (1, ex.LineNumber, "#1"); + // unlike unexpected element case which returned the position for '<', it does return the name start char... + Assert.AreEqual (70, ex.ColumnNumber, "#2"); + #endif + } + } + + [Test] + public void LoadUnregisteredItem () + { + string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><ItemGroup><UnregisteredItem Include='bar.txt' /></ItemGroup></Project>"; + var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual (1, root.Items.Count, "#1"); + } + + [Test] + public void LoadInvalidProjectForBadCondition () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo> + <!-- Note that this contains invalid Condition expression. Project.ctor() fails to load. --> + <Baz Condition=""$(Void)=="">$(FOO)</Baz> + </PropertyGroup> +</Project>"; + var path = "file://localhost/foo.xml"; + var reader = XmlReader.Create (new StringReader (xml), null, path); + var root = ProjectRootElement.Create (reader); + Assert.AreEqual (2, root.Properties.Count, "#1"); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void LoadInvalidProjectGroupInProjectGroup () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' /> + <PropertyGroup> + <Foo>Bar</Foo> + <PropertyGroup> + <X>x</X> + <Y>y</Y> + <Z>z</Z> + </PropertyGroup> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + ProjectRootElement.Create (xml); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void LoadInvalidItemGroupInProjectGroup () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' /> + <PropertyGroup> + <Foo>Bar</Foo> + <ItemGroup/> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + ProjectRootElement.Create (xml); + } + + [Test] + public void ChildAndAllChildren () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' /> + <PropertyGroup> + <Foo>Bar</Foo> + <Item/> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual (2, root.Children.Count, "#1"); + // AllChildren expands descendants + Assert.AreEqual (4, root.AllChildren.Count (), "#2"); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void SaveWithoutFullPath () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + root.Save (); + } + + [Test] + public void SaveToWriter () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + var sw = new StringWriter (); + root.Save (sw); + // CRLF? mmm, k... + Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n" + project_xml.Replace ('\'', '"'), sw.ToString (), "#1"); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void ImportsMissingProject () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='' /> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + ProjectRootElement.Create (xml); + } + } +} diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs new file mode 100644 index 0000000000..700a41663d --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectCollectionTest.cs @@ -0,0 +1,150 @@ +// +// ProjectCollectionTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using NUnit.Framework; +using Microsoft.Build.Execution; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ProjectCollectionTest + { + [Test] + public void GlobalProperties () + { + var g = ProjectCollection.GlobalProjectCollection; + Assert.AreEqual (0, g.GlobalProperties.Count, "#1"); + Assert.IsTrue (g.GlobalProperties.IsReadOnly, "#2"); + } + + [Test] + public void DefaultToolsVersion () + { + var pc = ProjectCollection.GlobalProjectCollection; + Assert.AreEqual (pc.Toolsets.First ().ToolsVersion, pc.DefaultToolsVersion, "#1"); + } + + [Test] + public void Toolsets () + { + var pc = ProjectCollection.GlobalProjectCollection; + Assert.IsNotNull (pc.Toolsets, "#1-1"); + Assert.IsTrue (pc.Toolsets.Any (), "#1-2"); + pc = new ProjectCollection (); + Assert.IsNotNull (pc.Toolsets, "#2-1"); + Assert.IsTrue (pc.Toolsets.Any (), "#2-2"); + } + + [Test] + public void BuildDoesNotIncreaseCollectionContent () + { + string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (empty_project_xml)); + var root = ProjectRootElement.Create (xml); + var coll = new ProjectCollection (); + var inst = new ProjectInstance (root, null, null, coll); + root.FullPath = "ProjectCollectionTest.BuildDoesNotIncreaseCollectionContent.proj"; + Assert.AreEqual (0, coll.Count, "#1"); + inst.Build (); + Assert.AreEqual (0, coll.Count, "#2"); + } + + [Test] + public void GetLoadedProjectsWithoutFullPath () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + string path = Path.GetFullPath ("foo.xml"); + var pc = new ProjectCollection (); + + pc.LoadProject (XmlReader.Create (new StringReader (project_xml), null, path)); + Assert.AreEqual (0, pc.GetLoadedProjects (path).Count, "#1"); // huh? + Assert.AreEqual (0, pc.LoadedProjects.Count, "#1.1"); + + new Project (root, null, null, pc); + Assert.AreEqual (0, pc.GetLoadedProjects (path).Count, "#2"); // huh? + } + + [Test] + public void GetLoadedProjectsSuccess () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + string path = Path.GetFullPath ("foo.xml"); + var pc = new ProjectCollection (); + + var proj = new Project (root, null, null, pc); + // this order also matters for test; It sets FullPath after Project.ctor(), and should still work. + root.FullPath = "foo.xml"; + + Assert.AreEqual (1, pc.GetLoadedProjects (path).Count, "#1"); // wow ok... + Assert.AreEqual (proj, pc.GetLoadedProjects (path).First (), "#2"); + } + + [Test] + public void GetLoadedProjectsSuccess2 () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + string path = Path.GetFullPath ("GetLoadedProjectsSuccess2.xml"); + var pc = new ProjectCollection (); + + using (var fs = File.CreateText (path)) + fs.Write (project_xml); + try { + var proj = pc.LoadProject (path); + + Assert.AreEqual (1, pc.GetLoadedProjects (path).Count, "#1"); // ok... LoadProject (with filename) adds it to the collection. + Assert.AreEqual (proj, pc.GetLoadedProjects (path).First (), "#2"); + } finally { + File.Delete (path); + } + } + + [Test] + public void GetLoadedProjectsForProjectInstance () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + string path = Path.GetFullPath ("foo.xml"); + var pc = new ProjectCollection (); + root.FullPath = "foo.xml"; + + new ProjectInstance (root, null, null, pc); + Assert.AreEqual (0, pc.GetLoadedProjects (path).Count, "#1"); // so, ProjectInstance does not actually load Project... + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemDefinitionTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemDefinitionTest.cs new file mode 100644 index 0000000000..cd86873c84 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemDefinitionTest.cs @@ -0,0 +1,104 @@ +// +// ProjectItemDefinitionTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using NUnit.Framework; +using System.Collections.Generic; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ProjectItemDefinitionTest + { + [Test] + public void Properties () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemDefinitionGroup> + <Foo> + <prop1>value1</prop1> + <prop2>value1</prop2> + </Foo> + <!-- This one is merged into existing Foo definition above. --> + <Foo> + <prop1>valueX1</prop1><!-- this one overrides value1. --> + <prop3>value3</prop3> + </Foo> + </ItemDefinitionGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + Assert.AreEqual (1, proj.ItemDefinitions.Count, "#1"); // Foo + var def = proj.ItemDefinitions ["Foo"]; + Assert.AreEqual ("Foo", def.ItemType, "#1x"); + Assert.AreEqual (3, def.MetadataCount, "#2"); + var md1 = def.Metadata.First (m => m.Name == "prop1"); + Assert.AreEqual ("Foo", md1.ItemType, "#2x"); + Assert.AreEqual ("valueX1", md1.UnevaluatedValue, "#3"); + // FIXME: enable it once we implemented it. + //Assert.AreEqual ("valueX1", md1.EvaluatedValue, "#4"); + Assert.IsNotNull (md1.Predecessor, "#5"); + Assert.AreEqual ("value1", md1.Predecessor.UnevaluatedValue, "#6"); + // FIXME: enable it once we implemented it. + //Assert.AreEqual ("value1", md1.Predecessor.EvaluatedValue, "#7"); + } + + [Test] + public void Condition () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemDefinitionGroup> + <I Condition='{0}'> + <DefinedMetadata>X</DefinedMetadata> + </I> + </ItemDefinitionGroup> + <ItemGroup> + <I Include='foo' /> + </ItemGroup> +</Project>"; + var reader = XmlReader.Create (new StringReader (string.Format (xml, "True"))); + var root = ProjectRootElement.Create (reader); + var proj = new Project (root); + var i = proj.GetItems ("I").First (); + Assert.AreEqual ("X", i.GetMetadataValue ("DefinedMetadata"), "#1"); + + reader = XmlReader.Create (new StringReader (string.Format (xml, "False"))); + root = ProjectRootElement.Create (reader); + proj = new Project (root); + i = proj.GetItems ("I").First (); + Assert.AreEqual (string.Empty, i.GetMetadataValue ("DefinedMetadata"), "#2"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemTest.cs new file mode 100644 index 0000000000..61973b7ceb --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemTest.cs @@ -0,0 +1,212 @@ +// +// ProjectItemTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using NUnit.Framework; +using System.Collections.Generic; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ProjectItemTest + { + [Test] + public void SetUnevaluatedInclude () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Include='foo/bar.txt' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual (1, root.ItemGroups.Count, "#1"); + var g = root.ItemGroups.First (); + Assert.AreEqual (1, g.Items.Count, "#2"); + var xitem = g.Items.First (); + var proj = new Project (root); + var item = proj.ItemsIgnoringCondition.First (); + string inc = "foo/bar.txt"; + Assert.AreEqual (inc, xitem.Include, "#3"); + Assert.AreEqual (inc, item.UnevaluatedInclude, "#4"); + string inc2 = "foo/bar.ext.txt"; + item.UnevaluatedInclude = inc2; + Assert.AreEqual (inc2, xitem.Include, "#5"); + Assert.AreEqual (inc2, item.UnevaluatedInclude, "#6"); + } + + void SetupTemporaryDirectoriesAndFiles () + { + Directory.CreateDirectory ("Test/ProjectItemTestTemporary"); + Directory.CreateDirectory ("Test/ProjectItemTestTemporary/parent"); + Directory.CreateDirectory ("Test/ProjectItemTestTemporary/parent/dir1"); + Directory.CreateDirectory ("Test/ProjectItemTestTemporary/parent/dir2"); + File.CreateText ("Test/ProjectItemTestTemporary/x.cs").Close (); + File.CreateText ("Test/ProjectItemTestTemporary/parent/dir1/a.cs").Close (); + File.CreateText ("Test/ProjectItemTestTemporary/parent/dir1/a1.cs").Close (); + File.CreateText ("Test/ProjectItemTestTemporary/parent/dir1/b.cs").Close (); + File.CreateText ("Test/ProjectItemTestTemporary/parent/dir2/a2.cs").Close (); + File.CreateText ("Test/ProjectItemTestTemporary/parent/dir2/a.cs").Close (); + File.CreateText ("Test/ProjectItemTestTemporary/parent/dir2/b.cs").Close (); + } + + void CleanupTemporaryDirectories () + { + Directory.Delete ("Test/ProjectItemTestTemporary", true); + } + + [Test] + public void WildcardExpansion () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Include='Test/ProjectItemTestTemporary/parent/dir*/a*.cs;Test/ProjectItemTestTemporary/x.cs' /> + </ItemGroup> +</Project>"; + try { + SetupTemporaryDirectoriesAndFiles (); + WildcardExpansionCommon (project_xml, false); + } finally { + CleanupTemporaryDirectories (); + } + } + + [Test] + public void WildcardExpansionRecursive () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Include='Test/ProjectItemTestTemporary/parent/**/a*.cs;Test/ProjectItemTestTemporary/x.cs' /> + </ItemGroup> +</Project>"; + try { + SetupTemporaryDirectoriesAndFiles (); + WildcardExpansionCommon (project_xml, true); + } finally { + CleanupTemporaryDirectories (); + } + } + + void WildcardExpansionCommon (string xmlString, bool hasRecursiveDir) + { + char sep = Path.DirectorySeparatorChar; + var xml = XmlReader.Create (new StringReader (xmlString)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + var xitem = proj.Xml.Items.First (); + // sort is needed because they are only sorted by ItemType. + var items = proj.Items.OrderBy (p => p.EvaluatedInclude).ToArray (); + Assert.AreEqual (5, items.Length, "#1"); + Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir1{0}a.cs", Path.DirectorySeparatorChar), items [0].EvaluatedInclude, "#2"); + Assert.AreEqual ("a", items [0].GetMetadataValue ("Filename"), "#3"); + if (hasRecursiveDir) + Assert.AreEqual ("dir1" + sep, items [0].GetMetadataValue ("RecursiveDir"), "#3.2"); + Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir1{0}a1.cs", Path.DirectorySeparatorChar), items [1].EvaluatedInclude, "#4"); + Assert.AreEqual ("a1", items [1].GetMetadataValue ("Filename"), "#5"); + if (hasRecursiveDir) + Assert.AreEqual ("dir1" + sep, items [1].GetMetadataValue ("RecursiveDir"), "#5.2"); + Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir2{0}a.cs", Path.DirectorySeparatorChar), items [2].EvaluatedInclude, "#6"); + Assert.AreEqual ("a", items [2].GetMetadataValue ("Filename"), "#7"); + if (hasRecursiveDir) + Assert.AreEqual ("dir2" + sep, items [2].GetMetadataValue ("RecursiveDir"), "#7.2"); + Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir2{0}a2.cs", Path.DirectorySeparatorChar), items [3].EvaluatedInclude, "#8"); + Assert.AreEqual ("a2", items [3].GetMetadataValue ("Filename"), "#9"); + if (hasRecursiveDir) + Assert.AreEqual ("dir2" + sep, items [3].GetMetadataValue ("RecursiveDir"), "#9.2"); + Assert.AreEqual ("Test/ProjectItemTestTemporary/x.cs", items [4].EvaluatedInclude, "#10"); + for (int i = 0; i < items.Length; i++) + Assert.AreEqual (xitem, items [i].Xml, "#11:" + i); + } + + [Test] + public void Metadata () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemDefinitionGroup> + <Foo> + <prop1>value1</prop1> + </Foo> + </ItemDefinitionGroup> + <ItemGroup> + <Foo Include='foo/bar.txt'> + <prop1>valueX1</prop1> + </Foo> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual (1, root.ItemGroups.Count, "#1"); + var g = root.ItemGroups.First (); + Assert.AreEqual (1, g.Items.Count, "#2"); + var proj = new Project (root); + var item = proj.ItemsIgnoringCondition.First (); + var meta = item.GetMetadata ("prop1"); + Assert.IsNotNull (meta, "#3"); + Assert.AreEqual ("valueX1", meta.UnevaluatedValue, "#4"); + Assert.IsNotNull (meta.Predecessor, "#5"); + Assert.AreEqual ("value1", meta.Predecessor.UnevaluatedValue, "#6"); + + // Well-known metadata don't show up via GetMetadata(), but does show up via GetMetadataValue(). + Assert.AreEqual (null, item.GetMetadata ("Filename"), "#7"); + Assert.AreEqual ("bar", item.GetMetadataValue ("Filename"), "#8"); + } + + [Test] + public void ExpandPropertyThenTrim () + { + string test = @"A +B +C + "; + string project_xml = string.Format (@"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Test>{0}</Test> + <Test2>$(TEST)</Test2> + </PropertyGroup> + <ItemGroup> + <X Include='$(TEST)' /> + <X2 Include='$(TEST)z' /> + </ItemGroup> +</Project>", test); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "ProjectItemTest.ExpandPropertyThenTrim.proj"; + var proj = new ProjectInstance (root); + Assert.AreEqual (test, proj.GetPropertyValue ("TEST"), "#1"); + Assert.AreEqual (test, proj.GetPropertyValue ("TEST2"), "#2"); + Assert.AreEqual (test.Trim (), proj.GetItems ("X").First ().EvaluatedInclude, "#3"); + Assert.AreEqual (test + "z", proj.GetItems ("X2").First ().EvaluatedInclude, "#4"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectPropertyTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectPropertyTest.cs new file mode 100644 index 0000000000..9c89ef09f6 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectPropertyTest.cs @@ -0,0 +1,130 @@ +// +// ProjectPropertyTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using NUnit.Framework; +using System.Collections.Generic; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ProjectPropertyTest + { + [Test] + public void SetUnevaluatedValueOverwritesElementValue () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Foo>Bar</Foo> + <Item/> + <X>1</X> + <X>2</X> + <PATH>overriden</PATH> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var pe = root.Properties.First (); + Assert.AreEqual ("Bar", pe.Value, "#1"); + var proj = new Project (root); + var prop = proj.Properties.First (p => p.Name == "Foo"); + Assert.AreEqual ("Bar", prop.UnevaluatedValue, "#2"); + prop.UnevaluatedValue = "x"; + Assert.AreEqual ("x", pe.Value, "#3"); + + prop = proj.Properties.First (p => p.Name == "X"); + Assert.AreEqual ("2", prop.UnevaluatedValue, "#4"); + Assert.IsNotNull (prop.Predecessor, "#5"); + Assert.AreEqual ("1", prop.Predecessor.UnevaluatedValue, "#6"); + + // environment property could also be Predecessor (and removed...maybe. + // I could reproduce only NRE = .NET bug with environment property so far.) + prop = proj.Properties.First (p => p.Name == "PATH"); + Assert.AreEqual ("overriden", prop.UnevaluatedValue, "#7"); + Assert.IsNotNull (prop.Predecessor, "#8"); + } + + [Test] + [ExpectedException (typeof(InvalidOperationException))] + public void UpdateGlobalPropertyValue () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var props = new Dictionary<string, string> (); + props.Add ("GP", "GV"); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root, props, null); + var pe = proj.Properties.First (p => p.IsGlobalProperty); + pe.UnevaluatedValue = "UPDATED"; + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void UpdateEnvironmentPropertyValue () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + var pe = proj.Properties.First (p => p.IsEnvironmentProperty); + pe.UnevaluatedValue = "UPDATED"; + } + + [Test] + public void DeepReferences () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <A>1</A> + <B>$(A)+1</B> + <C>$(B)+2</C> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + Assert.AreEqual ("1+1+2", new Project (root).GetProperty ("C").EvaluatedValue, "#1"); + Assert.AreEqual ("1+1+2", new ProjectInstance (root).GetProperty ("C").EvaluatedValue, "#1"); + } + + [Test] + public void PlatformPropertyEmptyByDefault () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + Assert.IsNull (proj.GetProperty ("PLATFORM"), "#1"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectTest.cs new file mode 100644 index 0000000000..4ea4551816 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectTest.cs @@ -0,0 +1,253 @@ +// +// ProjectTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using NUnit.Framework; +using Microsoft.Build.Exceptions; +using Microsoft.Build.Logging; +using Microsoft.Build.Framework; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ProjectTest + { + [Test] + public void EscapeDoesWTF () + { + string value_xml = "What are 'ESCAPE' & \"EVALUATE\" ? $ # % ^"; + string value = "What are 'ESCAPE' & \"EVALUATE\" ? $ # % ^"; + string escaped = "What are %27ESCAPE%27 & \"EVALUATE\" %3f %24 # %25 ^"; + string xml = string.Format (@"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Foo>{0}</Foo> + <Baz>$(FOO)</Baz> + </PropertyGroup> +</Project>", value_xml); + var path = "file://localhost/foo.xml"; + var reader = XmlReader.Create (new StringReader (xml), null, path); + var root = ProjectRootElement.Create (reader); + var proj = new Project (root); + var prop = proj.Properties.First (p => p.Name == "Foo"); + Assert.AreEqual (value, prop.UnevaluatedValue, "#1"); + Assert.AreEqual (value, prop.EvaluatedValue, "#2"); + // eh? + Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#3"); + prop = proj.Properties.First (p => p.Name == "Baz"); + Assert.AreEqual ("$(FOO)", prop.UnevaluatedValue, "#4"); + Assert.AreEqual (value, prop.EvaluatedValue, "#5"); + // eh? + Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#6"); + + // OK you are fine. + Assert.AreEqual (escaped, ProjectCollection.Escape (value), "#7"); + } + + [Test] + public void FullPath () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + proj.FullPath = "ABC"; + Assert.IsTrue (proj.FullPath.EndsWith (Path.DirectorySeparatorChar + "ABC"), "#1"); + Assert.AreEqual (root.FullPath, proj.FullPath, "#2"); + } + + [Test] + public void BuildEmptyProject () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + root.FullPath = "ProjectTest.BuildEmptyProject.proj"; + + // This seems to do nothing and still returns true + Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.1.proj" }.Build (), "#1"); + // This seems to fail to find the appropriate target + Assert.IsFalse (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.2.proj" }.Build ("Build", null), "#2"); + // Thus, this tries to build all the targets (empty) and no one failed, so returns true(!) + Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.3.proj" }.Build (new string [0], null), "#3"); + // Actially null "targets" is accepted and returns true(!!) + Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.4.proj" }.Build ((string []) null, null), "#4"); + // matching seems to be blindly done, null string also results in true(!!) + Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.5.proj" }.Build ((string) null, null), "#5"); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void LoadInvalidProjectForBadCondition () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo> + <!-- Note that this contains invalid Condition expression, yet ProjectElement.Create() does NOT fail. --> + <Baz Condition=""$(Void)=="">$(FOO)</Baz> + </PropertyGroup> +</Project>"; + var reader = XmlReader.Create (new StringReader (xml)); + var root = ProjectRootElement.Create (reader); + new Project (root); + } + + [Test] + public void ExpandString () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo> + <Bar>y</Bar> + <Baz Condition=""$(Void)==''"">$(FOO)</Baz> + </PropertyGroup> +</Project>"; + var reader = XmlReader.Create (new StringReader (xml)); + var root = ProjectRootElement.Create (reader); + var proj = new Project (root); + root.FullPath = "ProjectTest.ExpandString.proj"; + Assert.AreEqual ("xyz", proj.ExpandString ("x$(BAR)z"), "#1"); + Assert.AreEqual ("x$(BARz", proj.ExpandString ("x$(BARz"), "#2"); // incomplete + Assert.AreEqual ("xz", proj.ExpandString ("x@(BAR)z"), "#3"); // not an item + } + + [Test] + public void BuildCSharpTargetGetFrameworkPaths () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' /> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + root.FullPath = "ProjectTest.BuildCSharpTargetGetFrameworkPaths.proj"; + Assert.IsTrue (proj.Build ("GetFrameworkPaths", new ILogger [] {/*new ConsoleLogger ()*/})); + } + + [Test] + public void BuildCSharpTargetBuild () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <AssemblyName>Foo</AssemblyName> + </PropertyGroup> + <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' /> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "ProjectTest.BuildCSharpTargetBuild.proj"; + var proj = new Project (root, null, "4.0"); + Assert.IsFalse (proj.Build ("Build", new ILogger [] {/*new ConsoleLogger (LoggerVerbosity.Diagnostic)*/})); // missing mandatory properties + } + + [Test] + public void EvaluateItemConditionThenIgnored () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <P></P> + </PropertyGroup> + <ItemGroup> + <Foo Condition='' Include='x' /> + <Bar Include='$(P)' /> + <Baz Include='z' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + // note that Foo is ignored BUT Bar is NOT ignored. + Assert.AreEqual (2, proj.ItemsIgnoringCondition.Count, "#1"); + Assert.IsNotNull ("Bar", proj.ItemsIgnoringCondition.First ().ItemType, "#2"); + Assert.IsNotNull ("Baz", proj.ItemsIgnoringCondition.Last ().ItemType, "#3"); + } + + [Test] + public void EvaluateSamePropertiesInOrder () + { + // used in Microsoft.Common.targets + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <BaseIntermediateOutputPath Condition=""'$(BaseIntermediateOutputPath)' == ''"">obj\</BaseIntermediateOutputPath> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + Assert.AreEqual ("obj\\", proj.GetPropertyValue ("BaseIntermediateOutputPath"), "#1"); + } + + [Test] + public void DirtyMarking () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + Assert.IsFalse (proj.IsDirty, "#1"); + proj.MarkDirty (); + Assert.IsTrue (proj.IsDirty, "#2"); + } + + [Test] + public void DirtyMarking2 () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); + proj.DisableMarkDirty = true; + proj.MarkDirty (); + Assert.IsFalse (proj.IsDirty, "#1"); // not rejected, just ignored. + proj.DisableMarkDirty = false; + Assert.IsFalse (proj.IsDirty, "#2"); // not like status pending + proj.MarkDirty (); + Assert.IsTrue (proj.IsDirty, "#3"); + } + + [Test] + public void CreateProjectInstance () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <AssemblyName>Foo</AssemblyName> + </PropertyGroup> + <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' /> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root, null, "4.0"); + var inst = proj.CreateProjectInstance (); + Assert.AreEqual ("4.0", inst.ToolsVersion, "#1"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ResolvedImportTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ResolvedImportTest.cs new file mode 100644 index 0000000000..9c4359ee7a --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ResolvedImportTest.cs @@ -0,0 +1,181 @@ +// +// ResolvedImportTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using NUnit.Framework; +using Microsoft.Build.Exceptions; +using Microsoft.Build.Framework; +using Microsoft.Build.Execution; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ResolvedImportTest + { + const string temp_file_name = "test_imported.proj"; + + [Test] + public void SimpleImportAndSemanticValues () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='test_imported.proj' /> +</Project>"; + string imported = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <A>x</A> + <B>y</B> + </PropertyGroup> + <ItemGroup> + <X Include=""included.txt"" /> + </ItemGroup> +</Project>"; + using (var ts = File.CreateText (temp_file_name)) + ts.Write (imported); + try { + var reader = XmlReader.Create (new StringReader (xml)); + var root = ProjectRootElement.Create (reader); + Assert.AreEqual (temp_file_name, root.Imports.First ().Project, "#1"); + var proj = new Project (root); + var prop = proj.GetProperty ("A"); + Assert.IsNotNull (prop, "#2"); + Assert.IsTrue (prop.IsImported, "#3"); + var item = proj.GetItems ("X").FirstOrDefault (); + Assert.IsNotNull (item, "#4"); + Assert.AreEqual ("included.txt", item.EvaluatedInclude, "#5"); + } finally { + File.Delete (temp_file_name); + } + } + + string import_overrides_test_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <A>X</A> + </PropertyGroup> + <Import Condition=""{0}"" Project='test_imported.proj' /> + <PropertyGroup> + <B>Y</B> + </PropertyGroup> +</Project>"; + string import_overrides_test_imported = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <C Condition='$(A)==x'>c</C> + <A>a</A> + <B>b</B> + </PropertyGroup> + <ItemGroup> + <X Include=""included.txt"" /> + </ItemGroup> +</Project>"; + + void ImportAndPropertyOverrides (string label, string condition, string valueA, string valueB, string valueAPredecessor, bool existsC) + { + using (var ts = File.CreateText (temp_file_name)) + ts.Write (import_overrides_test_imported); + try { + string xml = string.Format (import_overrides_test_xml, condition); + var reader = XmlReader.Create (new StringReader (xml)); + var root = ProjectRootElement.Create (reader); + var proj = new Project (root); + var a = proj.GetProperty ("A"); + Assert.IsNotNull (a, label + "#2"); + Assert.AreEqual (valueA, a.EvaluatedValue, label + "#3"); + if (valueAPredecessor == null) + Assert.IsNull (a.Predecessor, label + "#3.1"); + else { + Assert.IsNotNull (a.Predecessor, label + "#3.2"); + Assert.AreEqual (valueAPredecessor, a.Predecessor.EvaluatedValue, label + "#3.3"); + } + var b = proj.GetProperty ("B"); + Assert.IsNotNull (b, label + "#4"); + Assert.AreEqual (valueB, b.EvaluatedValue, label + "#5"); + var c = proj.GetProperty ("C"); // yes it can be retrieved. + if (existsC) { + Assert.IsNotNull (c, label + "#6"); + Assert.AreEqual ("c", c.EvaluatedValue, label + "#7"); + } + else + Assert.IsNull (c, label + "#8"); + } finally { + File.Delete (temp_file_name); + } + } + + [Test] + public void ImportAndPropertyOverrides () + { + ImportAndPropertyOverrides ("[1]", "'True'", "a", "Y", "X", true); + ImportAndPropertyOverrides ("[2]", "$(A)=='X'", "a", "Y", "X", true); // evaluated as true + ImportAndPropertyOverrides ("[3]", "$(B)=='Y'", "X", "Y", null, false); // evaluated as false + ImportAndPropertyOverrides ("[4]", "$(B)=='b'", "X", "Y", null, false); // of course not evaluated with imported value + } + + // FIXME: + // Looks like $(MSBuildThisFile) is available only within property value, not via .NET MSBuild API. + // Right now our variable is added as a Reserved property, but we will have to hide it. + // + [Test] + public void EvaluateMSBuildThisFileProperty () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <A>$(MSBuildThisFile)</A> + </PropertyGroup> + <Import Project='test_imported.proj' /> +</Project>"; + string imported = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <B>$(MSBuildThisFile)</B> + </PropertyGroup> +</Project>"; + using (var ts = File.CreateText (temp_file_name)) + ts.Write (imported); + try { + var reader = XmlReader.Create (new StringReader (xml)); + var root = ProjectRootElement.Create (reader); + var proj = new Project (root); + var a = proj.GetProperty ("A"); + Assert.AreEqual (string.Empty, a.EvaluatedValue, "#1"); + var b = proj.GetProperty ("B"); + Assert.AreEqual (temp_file_name, b.EvaluatedValue, "#2"); + + var pi = new ProjectInstance (root); + var ai = pi.GetProperty ("A"); + Assert.AreEqual (string.Empty, ai.EvaluatedValue, "#3"); + var bi = pi.GetProperty ("B"); + Assert.AreEqual (temp_file_name, bi.EvaluatedValue, "#4"); + } finally { + File.Delete (temp_file_name); + } + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs new file mode 100644 index 0000000000..ac4e2d6610 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ToolsetTest.cs @@ -0,0 +1,53 @@ +// +// ToolSetTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using Microsoft.Build.Evaluation; +using NUnit.Framework; + +namespace MonoTests.Microsoft.Build.Evaluation +{ + [TestFixture] + public class ToolsetTest + { + [Test] + public void Constructor () + { + var ts = new Toolset ("4.3", "c:\\", ProjectCollection.GlobalProjectCollection, null); + Assert.IsNotNull (ts.Properties, "#1"); + Assert.AreEqual (0, ts.Properties.Count, "#2"); +#if NET_4_5 + Assert.IsNull (ts.DefaultSubToolsetVersion, "#3"); + Assert.IsNotNull (ts.SubToolsets, "#4"); + Assert.AreEqual (0, ts.SubToolsets.Count, "#5"); +#endif + Assert.AreEqual ("c:\\", ts.ToolsPath, "#6"); + Assert.AreEqual ("4.3", ts.ToolsVersion, "#7"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildManagerTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildManagerTest.cs new file mode 100644 index 0000000000..0fcbdf7560 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildManagerTest.cs @@ -0,0 +1,201 @@ +// +// BuildManagerTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using NUnit.Framework; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Logging; + +namespace MonoTests.Microsoft.Build.Execution +{ + [TestFixture] + public class BuildManagerTest + { + Project GetDummyProject () + { + string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var path = "file://localhost/foo.xml"; + var xml = XmlReader.Create (new StringReader (empty_project_xml), null, path); + var root = ProjectRootElement.Create (xml); + return new Project (root); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void GetProjectInstanceForBuildNullFullPath () + { + var manager = new BuildManager (); + manager.GetProjectInstanceForBuild (GetDummyProject ()); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public void GetProjectInstanceForBuildEmptyFullPath () + { + var proj = GetDummyProject (); + proj.FullPath = ""; + var manager = new BuildManager (); + manager.GetProjectInstanceForBuild (proj); + } + + [Test] + public void GetProjectInstanceForBuild () + { + string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var path = "file://localhost/foo.xml"; + var xml = XmlReader.Create (new StringReader(empty_project_xml), null, path); + var root = ProjectRootElement.Create (xml); + root.FullPath = path; + var proj = new Project (root); + var manager = new BuildManager (); + var inst = manager.GetProjectInstanceForBuild (proj); + Assert.AreEqual (inst, manager.GetProjectInstanceForBuild (proj), "#1"); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void PendBuildRequestBeforeBeginBuild () + { + string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var path = "file://localhost/foo.xml"; + var xml = XmlReader.Create (new StringReader (empty_project_xml), null, path); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + new BuildManager ().PendBuildRequest (new BuildRequestData (proj, new string [0])); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void ResetCachesDuringBuildIsInvalid () + { + // Windows does not have useful sleep or alternative, so skip it + bool is_windows = true; + switch (Environment.OSVersion.Platform) { + case PlatformID.Unix: + case PlatformID.MacOSX: + is_windows = false; + break; + } + string project_xml = string.Format (@"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Target Name='Wait1Sec'> + <Exec Command='{0}' /> + </Target> +</Project>", is_windows ? "powershell -command \"Start-Sleep -s 1\"" : "/bin/sleep 1"); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + var bm = new BuildManager (); + bm.BeginBuild (new BuildParameters ()); + var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" })); + sub.ExecuteAsync (delegate {}, null); + try { + bm.ResetCaches (); + } finally { + bm.EndBuild (); // yes, it should work even after invalid ResetCaches call... at least on .NET it does. + } + } + + [Test] + public void BasicManualParallelBuilds () + { + string project_xml = @"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Target Name='Wait1Sec'> + <!-- Exec Command='ping 10.1.1.1 -n 1 -w 1' /--> + <Exec Command='/bin/sleep 1' /> + </Target> +</Project>"; + switch (Environment.OSVersion.Platform) { + case PlatformID.MacOSX: + case PlatformID.Unix: + break; + default: + return; // ignore, cannot run it + } + + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + var bm = new BuildManager (); + bm.BeginBuild (new BuildParameters () { Loggers = new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic, TextWriter.Null.WriteLine, null, null)} }); + DateTime waitDone = DateTime.MinValue; + DateTime beforeExec = DateTime.Now; + var l = new List<BuildSubmission> (); + for (int i = 0; i < 10; i++) { + var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" })); + l.Add (sub); + sub.ExecuteAsync (delegate { waitDone = DateTime.Now; }, null); + } + bm.EndBuild (); + Assert.IsTrue (l.All (s => s.BuildResult.OverallResult == BuildResultCode.Success), "#1"); + DateTime endBuildDone = DateTime.Now; + Assert.IsTrue (endBuildDone - beforeExec >= TimeSpan.FromSeconds (1), "#2"); + Assert.IsTrue (endBuildDone > waitDone, "#3"); + } + + [Test] + public void BuildCommonResolveAssemblyReferences () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' /> + <ItemGroup> + <Reference Include='System.Core' /> + <Reference Include='System.Xml' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "BuildManagerTest.BuildCommonResolveAssemblyReferences.proj"; + var proj = new ProjectInstance (root); + var manager = new BuildManager (); + var parameters = new BuildParameters () { Loggers = new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic)} }; + var request = new BuildRequestData (proj, new string [] {"ResolveAssemblyReferences"}); + Assert.AreEqual (string.Empty, proj.GetPropertyValue ("TargetFrameworkDirectory"), "#1-1"); + var result = manager.Build (parameters, request); + Assert.AreNotEqual (string.Empty, proj.GetPropertyValue ("TargetFrameworkDirectory"), "#1-2"); // filled during build. + Assert.IsTrue (result.ResultsByTarget.ContainsKey ("GetFrameworkPaths"), "#2-1"); + Assert.IsTrue (result.ResultsByTarget.ContainsKey ("PrepareForBuild"), "#2-2"); + Assert.IsTrue (result.ResultsByTarget.ContainsKey ("ResolveAssemblyReferences"), "#2-3"); + var items = proj.GetItems ("ReferencePath"); + Assert.AreEqual (2, items.Count (), "#3"); + var syscore = items.FirstOrDefault (i => Path.GetFileName (i.EvaluatedInclude) == "System.Core.dll"); + var sysxml = items.FirstOrDefault (i => Path.GetFileName (i.EvaluatedInclude) == "System.Xml.dll"); + Assert.IsNotNull (syscore, "#4-1"); + Assert.IsNotNull (sysxml, "#4-2"); + Assert.IsTrue (File.Exists (syscore.EvaluatedInclude), "#5-1"); + Assert.IsTrue (File.Exists (sysxml.EvaluatedInclude), "#5-1"); + Assert.AreEqual (BuildResultCode.Success, result.OverallResult, "#6"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildParametersTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildParametersTest.cs new file mode 100644 index 0000000000..47cd5f9007 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildParametersTest.cs @@ -0,0 +1,66 @@ +// +// BuildParametersTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using NUnit.Framework; + +namespace MonoTests.Microsoft.Build.Execution +{ + [TestFixture] + public class BuildParametersTest + { + [Test] + public void GetToolset () + { + var bp = new BuildParameters (ProjectCollection.GlobalProjectCollection); + Assert.IsNull (bp.GetToolset ("0.1"), "#1"); + var ts = bp.GetToolset ("2.0"); + // They are equal + Assert.AreEqual (ProjectCollection.GlobalProjectCollection.Toolsets.First (t => t.ToolsVersion == "2.0"), ts, "#2"); + + bp = new BuildParameters (); + Assert.IsNull (bp.GetToolset ("0.1"), "#1"); + ts = bp.GetToolset ("2.0"); + // They are NOT equal, because ProjectCollection seems to be different. + Assert.AreNotEqual (ProjectCollection.GlobalProjectCollection.Toolsets.First (t => t.ToolsVersion == "2.0"), ts, "#2"); + } + + [Test] + public void PropertiesDefault () + { + var bp = new BuildParameters (); + Assert.IsTrue (bp.EnableNodeReuse, "#1"); + Assert.IsTrue (bp.EnvironmentProperties.Count > 0, "#2"); + Assert.AreEqual (CultureInfo.CurrentCulture, bp.Culture, "#3"); + } + } +} diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildSubmissionTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildSubmissionTest.cs new file mode 100644 index 0000000000..df2febcbf7 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildSubmissionTest.cs @@ -0,0 +1,115 @@ +// +// BuildSubmissionTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using NUnit.Framework; +using Microsoft.Build.Logging; +using Microsoft.Build.Framework; +using System.Collections.Generic; + +namespace MonoTests.Microsoft.Build.Execution +{ + [TestFixture] + public class BuildSubmissionTest + { + [Test] + public void ResultBeforeExecute () + { + string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var path = "file://localhost/foo.xml"; + var xml = XmlReader.Create (new StringReader (empty_project_xml), null, path); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + var bm = new BuildManager (); + bm.BeginBuild (new BuildParameters ()); + var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [0])); + Assert.IsNull (sub.BuildResult, "#1"); + } + + // This checks if the build output for each task is written to the loggers and not directly thrown as a Project loader error. + [Test] + public void TaskOutputsToLoggers () + { + string project_xml = @"<Project DefaultTargets='Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' /> + <Target Name='Foo'> + <ItemGroup> + <Foo Condition='$(X)' Include='foo.txt' /> + </ItemGroup> + </Target> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "BuildSubmissionTest.TaskOutputsToLoggers.proj"; + var proj = new ProjectInstance (root); + Assert.AreEqual ("$(X)", root.Targets.First ().ItemGroups.First ().Items.First ().Condition, "#0"); + var sw = new StringWriter (); + Assert.IsFalse (proj.Build (new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic, sw.WriteLine, null, null)}), "#1"); + Assert.IsTrue (sw.ToString ().Contains ("$(X)"), "#2"); + } + + [Test] + public void EndBuildWaitsForSubmissionCompletion () + { + // Windows does not have useful sleep or alternative, so skip it + bool is_windows = true; + switch (Environment.OSVersion.Platform) { + case PlatformID.Unix: + case PlatformID.MacOSX: + is_windows = false; + break; + } + string project_xml = string.Format (@"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Target Name='Wait1Sec'> + <Exec Command='{0}' /> + </Target> +</Project>", is_windows ? "powershell -command \"Start-Sleep -s 1\"" : "/bin/sleep 1"); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "BuildSubmissionTest.EndBuildWaitsForSubmissionCompletion.proj"; + var proj = new ProjectInstance (root); + var bm = new BuildManager (); + bm.BeginBuild (new BuildParameters ()); + DateTime waitDone = DateTime.MinValue; + DateTime beforeExec = DateTime.Now; + var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" })); + sub.ExecuteAsync (delegate { waitDone = DateTime.Now; }, null); + bm.EndBuild (); + Assert.IsTrue (sub.BuildResult.OverallResult == BuildResultCode.Success, "#1"); + DateTime endBuildDone = DateTime.Now; + Assert.IsTrue (endBuildDone - beforeExec >= TimeSpan.FromSeconds (1), "#2"); + Assert.IsTrue (endBuildDone > waitDone, "#3"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectInstanceTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectInstanceTest.cs new file mode 100644 index 0000000000..327aa389c4 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectInstanceTest.cs @@ -0,0 +1,103 @@ +// +// ProjectInstanceTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Execution; +using NUnit.Framework; +using Microsoft.Build.Evaluation; + +namespace MonoTests.Microsoft.Build.Execution +{ + [TestFixture] + public class ProjectInstanceTest + { + [Test] + public void ItemsAndProperties () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <X Condition='false' Include='bar.txt' /> + <X Include='foo.txt'> + <M>m</M> + <N>=</N> + </X> + </ItemGroup> + <PropertyGroup> + <P Condition='false'>void</P> + <P Condition='true'>valid</P> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader(project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + var item = proj.Items.First (); + Assert.AreEqual ("foo.txt", item.EvaluatedInclude, "#1"); + var prop = proj.Properties.First (p => p.Name=="P"); + Assert.AreEqual ("valid", prop.EvaluatedValue, "#2"); + Assert.IsNotNull (proj.GetProperty ("MSBuildProjectDirectory"), "#3"); + Assert.AreEqual ("2.0", proj.ToolsVersion, "#4"); + } + + [Test] + public void ExplicitToolsVersion () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader(project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root, null, "4.0", new ProjectCollection ()); + Assert.AreEqual ("4.0", proj.ToolsVersion, "#1"); + } + + [Test] + public void BuildEmptyProject () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />"; + var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml"); + var root = ProjectRootElement.Create (xml); + // This seems to do nothing and still returns true + root.FullPath = "ProjectInstanceTest.BuildEmptyProject.1.proj"; + Assert.IsTrue (new ProjectInstance (root).Build (), "#1"); + // This seems to fail to find the appropriate target + root.FullPath = "ProjectInstanceTest.BuildEmptyProject.2.proj"; + Assert.IsFalse (new ProjectInstance (root).Build ("Build", null), "#2"); + // Thus, this tries to build all the targets (empty) and no one failed, so returns true(!) + root.FullPath = "ProjectInstanceTest.BuildEmptyProject.3.proj"; + Assert.IsTrue (new ProjectInstance (root).Build (new string [0], null), "#3"); + // Actially null "targets" is accepted and returns true(!!) + root.FullPath = "ProjectInstanceTest.BuildEmptyProject.4.proj"; + Assert.IsTrue (new ProjectInstance (root).Build ((string []) null, null), "#4"); + // matching seems to be blindly done, null string also results in true(!!) + root.FullPath = "ProjectInstanceTest.BuildEmptyProject.5.proj"; + Assert.IsTrue (new ProjectInstance (root).Build ((string) null, null), "#5"); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectMetadataInstanceTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectMetadataInstanceTest.cs new file mode 100644 index 0000000000..5c136d6b60 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectMetadataInstanceTest.cs @@ -0,0 +1,78 @@ +// +// ProjectMetadataInstanceTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Execution; +using NUnit.Framework; + +namespace MonoTests.Microsoft.Build.Execution +{ + [TestFixture] + public class ProjectMetadataInstanceTest + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <X Include='foo.txt'> + <M>m</M> + <N>=</N> + </X> + </ItemGroup> +</Project>"; + + [Test] + public void PropertiesCopiesValues () + { + var xml = XmlReader.Create (new StringReader (project_xml)); + string path = Path.GetFullPath ("foo.xml"); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + var item = proj.Items.First (); + var md = item.Metadata.First (); + Assert.AreEqual ("m", item.Metadata.First ().EvaluatedValue, "#1"); + Assert.AreEqual ("m", root.ItemGroups.First ().Items.First ().Metadata.First ().Value, "#2"); + root.ItemGroups.First ().Items.First ().Metadata.First ().Value = "X"; + Assert.AreEqual ("m", item.Metadata.First ().EvaluatedValue, "#3"); + } + + [Test] + public void ToStringOverride () + { + var xml = XmlReader.Create (new StringReader (project_xml)); + string path = Path.GetFullPath ("foo.xml"); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + var item = proj.Items.First (); + Assert.AreEqual ("M=m", item.Metadata.First ().ToString (), "#1"); + Assert.AreEqual ("N==", item.Metadata.Last ().ToString (), "#2"); // haha + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs new file mode 100644 index 0000000000..2ae7148c8f --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/ProjectTargetInstanceTest.cs @@ -0,0 +1,172 @@ +// +// ProjectTargetInstanceTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Execution; +using NUnit.Framework; +using Microsoft.Build.Logging; +using Microsoft.Build.Framework; + +namespace MonoTests.Microsoft.Build.Execution +{ + [TestFixture] + public class ProjectTargetInstanceTest + { + [Test] + public void DefaultTargetsEmpty () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + Assert.AreEqual (new string [0], proj.DefaultTargets, "#1"); + } + + [Test] + public void DefaultTargetsFromAttribute () + { + string project_xml = @"<Project DefaultTargets='Foo Bar Baz;Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + string [] expected = {"Foo Bar Baz", "Foo"}; + Assert.AreEqual (expected, proj.DefaultTargets, "#1"); + } + + [Test] + public void DefaultTargetsFromElements () + { + string [] defaultTargetAtts = {string.Empty, "DefaultTargets=''"}; + + for (int i = 0; i < defaultTargetAtts.Length; i++) { + string project_xml = string.Format (@"<Project {0} xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Target Name='Foo' /> + <Target Name='Bar' /> +</Project>", defaultTargetAtts [i]); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + string [] expected = {"Foo"}; // Bar is not included + Assert.AreEqual (expected, proj.DefaultTargets, "#1-" + i); + } + } + + [Test] + public void MicrosoftCommonTargets () + { + string [] defaultTargetAtts = { string.Empty, "DefaultTargets=''" }; + + for (int i = 0; i < defaultTargetAtts.Length; i++) { + string project_xml = string.Format (@"<Project {0} xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' /> +</Project>", defaultTargetAtts [i]); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + Assert.AreEqual ("Build", proj.DefaultTargets.FirstOrDefault (), "#1-" + i); + } + } + + [Test] + public void DefaultTargetsOverride () + { + string project_xml = @"<Project DefaultTargets='Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' /> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new ProjectInstance (root); + Assert.AreEqual ("Foo", proj.DefaultTargets.FirstOrDefault (), "#1"); + } + + [Test] + public void MultipleDefaultTargets () + { + bool[] expected = { true, false, true }; + string [] defaultTargets = {"Foo", "Foo;Bar", "Foo;Bar"}; + string [] targets = { string.Empty, string.Empty, "<Target Name='Bar' />" }; + for (int i = 0; i < expected.Length; i++) { + string project_xml = string.Format (@"<Project DefaultTargets='{0}' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' /> + <Target Name='Foo' /> + {1} +</Project>", defaultTargets [i], targets [i]); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = string.Format ("ProjectInstanceTest.MultipleDefaultTargets.{0}.proj", i); + var proj = new ProjectInstance (root); + Assert.AreEqual ("Foo", proj.DefaultTargets.FirstOrDefault (), "#1-" + i); + Assert.AreEqual (expected [i], proj.Build (), "#2-" + i); + } + } + + [Test] + public void DependsOnTargets () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Target Name='Bar' DependsOnTargets='Foo' /> + <Target Name='Foo'> + <Error Text='expected error' /> + </Target> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "ProjectInstanceTest.DependsOnTargets.proj"; + var proj = new ProjectInstance (root); + Assert.AreEqual (2, proj.Targets.Count, "#1"); + Assert.IsFalse (proj.Build ("Bar", new ILogger [0]), "#2"); + } + + [Test] + public void InputsAndOutputs () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <Target Name='Foo' Inputs='inputsandoutputstest.txt' Outputs='inputsandoutputstest.txt'> + <Error Text='error' /> + </Target> +</Project>"; + try { + if (!File.Exists ("inputsandoutputstest.txt")) + File.CreateText ("inputsandoutputstest.txt").Close (); + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + root.FullPath = "ProjectTargetInstanceTest.InputsAndOutputs.proj"; + var proj = new ProjectInstance (root); + Assert.IsTrue (proj.Build (), "#1"); // if it does not skip Foo, it results in an error. + } finally { + if (File.Exists ("inputsandoutputstest.txt")) + File.Delete ("inputsandoutputstest.txt"); + } + } + } +} diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Internal/ExpressionParserTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Internal/ExpressionParserTest.cs new file mode 100644 index 0000000000..7654538a1a --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Internal/ExpressionParserTest.cs @@ -0,0 +1,287 @@ +// +// ExpressionParserTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using NUnit.Framework; +using Microsoft.Build.Execution; +using Microsoft.Build.Exceptions; +using System.Collections.Generic; + +namespace MonoTests.Microsoft.Build.Internal +{ + [TestFixture] + public class ExpressionParserTest + { + string [] invalid_always = { + "$(Foo..Bar)", + "$([DateTime.Now])", // fullname required + "$([System.DateTime.Now])", // member cannot be invoked with '.' + }; + string [] invalid_as_boolean = { + "$", + "@", + "%", + "%-1", + "$(", + "%(", + "$)", + "%)", + "%24", + "()", + "{}", + "A", // must be evaluated as a boolean + "1", // ditto (no default conversion to bool) + "$ (foo) == ''", + "@ (foo) == ''", + "$(1)", + "$(Foo) == And", // reserved keyword 'and' + "$(Foo) == Or", // reserved keyword 'or' + "$(Foo) == $(Bar) == $(Baz)", // unexpected '==' + "$([System.DateTime]::Now)", // it is DateTime + "$([System.String]::Format('Tr'))$([System.String]::Format('ue'))", // only one expression is accepted + "$([System.String]::Format(null))", // causing ANE, wrapped by InvalidProjectFileException + "yep", + "nope", + "ONN", + "OFFF", + }; + string [] valid = { + "'%24' == 0", + "true", + "fAlSe", + "(false)", + "A==A", + "A ==A", + "A== A", + "A=='A'", + "A==\tA", + "\tA== A", + "$([System.String]::Format('True'))", + "$([System.String]::Format('True', null))", + "False And True == True And True", + "True or True or False", + "(True or True or False)", + "True and False", + "(True) and (False)", + "yes", + "nO", + "oN", + "oFf", + }; + string [] depends = { + // valid only if evaluated to boolean + "$(foo)", + "@(foo)", + }; + + [Test] + public void EvaluateAsBoolean () + { + foreach (var expr in invalid_always.Concat (invalid_as_boolean).Concat (valid)) { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Condition=""{0}"" Include='x' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (string.Format (project_xml, expr))); + var root = ProjectRootElement.Create (xml); + try { + new Project (root); + if (invalid_as_boolean.Contains (expr) || invalid_always.Contains (expr)) + Assert.Fail ("Parsing Condition '{0}' should fail", expr); + } catch (Exception ex) { + if (valid.Contains (expr)) + throw new Exception (string.Format ("failed to parse '{0}'", expr), ex); + else if (ex is InvalidProjectFileException) + continue; + throw new Exception (string.Format ("unexpected exception to parse '{0}'", expr), ex); + } + } + } + + [Test] + public void EvaluateAsString () + { + foreach (var expr in invalid_always.Concat (invalid_as_boolean).Concat (valid)) { + try { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Include=""{0}"" /> + </ItemGroup> + </Project>"; + var xml = XmlReader.Create (new StringReader (string.Format (project_xml, expr))); + var root = ProjectRootElement.Create (xml); + // everything but 'invalid_always' should pass + new Project (root); + } catch (Exception ex) { + if (!invalid_always.Contains (expr)) + throw new Exception (string.Format ("failed to parse '{0}'", expr), ex); + } + } + } + + [Test] + public void EvaluatePropertyReferencesWithProperties () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Condition=""$(foo)"" Include='x' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var props = new Dictionary<string,string> (); + props ["foo"] = "true"; + new Project (root, props, null); + } + + [Test] + public void EvaluateItemReferences () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Include='false' /> + <!-- by the time Bar is evaluated, Foo is already evaluated and taken into consideration in expansion --> + <Bar Condition=""@(foo)"" Include='x' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + new Project (root); + } + + [Test] + public void EvaluateReferencesWithoutProperties () + { + foreach (var expr in depends) { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Foo Condition=""{0}"" Include='x' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (string.Format (project_xml, expr))); + var root = ProjectRootElement.Create (xml); + try { + new Project (root); + Assert.Fail ("Parsing Condition '{0}' should fail", expr); + } catch (InvalidProjectFileException) { + continue; + } + } + } + + [Test] + public void SemicolonHandling () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <Foo Condition=""'A;B'=='A;B'"">'A;B'</Foo> + </PropertyGroup> + <ItemGroup> + <Bar Include='$(Foo)' /> + </ItemGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); // at this state property is parsed without error i.e. Condition evaluates fine. + var prop = proj.GetProperty ("Foo"); + Assert.AreEqual ("'A;B'", prop.EvaluatedValue, "#1"); + var items = proj.GetItems ("Bar"); + Assert.AreEqual ("'A", items.First ().EvaluatedInclude, "#2"); + Assert.AreEqual ("$(Foo)", items.First ().UnevaluatedInclude, "#3"); + Assert.AreEqual (2, items.Count, "#4"); + Assert.AreEqual ("B'", items.Last ().EvaluatedInclude, "#5"); + Assert.AreEqual ("$(Foo)", items.Last ().UnevaluatedInclude, "#6"); + Assert.IsTrue (items.First ().Xml == items.Last ().Xml, "#7"); + } + + // the same as above except that ItemGroup goes first (and yet evaluated the same). + [Test] + public void EvaluationOrderPropertiesPrecedesItems () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Bar Include='$(Foo)' /> + </ItemGroup> + <PropertyGroup> + <Foo Condition=""'A;B'=='A;B'"">'A;B'</Foo> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + var proj = new Project (root); // at this state property is parsed without error i.e. Condition evaluates fine. + var prop = proj.GetProperty ("Foo"); + Assert.AreEqual ("'A;B'", prop.EvaluatedValue, "#1"); + var items = proj.GetItems ("Bar"); + Assert.AreEqual ("'A", items.First ().EvaluatedInclude, "#2"); + Assert.AreEqual ("$(Foo)", items.First ().UnevaluatedInclude, "#3"); + Assert.AreEqual (2, items.Count, "#4"); + Assert.AreEqual ("B'", items.Last ().EvaluatedInclude, "#5"); + Assert.AreEqual ("$(Foo)", items.Last ().UnevaluatedInclude, "#6"); + Assert.IsTrue (items.First ().Xml == items.Last ().Xml, "#7"); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void PropertyReferencesItem () + { + string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <ItemGroup> + <Bar Include='True' /> + </ItemGroup> + <PropertyGroup> + <Foo Condition='@(Bar)'>X</Foo><!-- not allowed --> + </PropertyGroup> +</Project>"; + var xml = XmlReader.Create (new StringReader (project_xml)); + var root = ProjectRootElement.Create (xml); + new Project (root); + } + + [Test] + [ExpectedException (typeof (InvalidProjectFileException))] + public void SequentialPropertyReferenceNotAllowed () + { + string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'> + <PropertyGroup> + <A>x</A> + <B>y</B> + <C Condition=""$(A)$(B)==''"">z</C> + </PropertyGroup> +</Project>"; + var reader = XmlReader.Create (new StringReader (xml)); + var root = ProjectRootElement.Create (reader); + new Project (root); + } + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Logging/ConsoleLoggerTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Logging/ConsoleLoggerTest.cs new file mode 100644 index 0000000000..0135393d9e --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Logging/ConsoleLoggerTest.cs @@ -0,0 +1,102 @@ +// +// ConsoleLoggerTest.cs +// +// Author: +// Atsushi Enomoto (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Logging; +using NUnit.Framework; + +namespace MonoTests.Microsoft.Build.Logging +{ + [TestFixture] + public class ConsoleLoggerTest + { + // Unfortunately, the existing code in MS.Build.Engine.dll has slightly different + // format. We'd rather use already complete implementation, just disabled this test. + [Test] + [Category ("NotWorking")] + public void BasicLoggerUsage () + { + string expected = @"file : cat error code: msg + +file : cat warning code: msg + +__________________________________________________ + +Project ""project.txt"" (target target(s)): + + + +Build started 2013/01/01 00:00:00. + +Target ""target"" in file ""target.txt"": + + start task + + finished task + +finished target + + + +finished project + + + +finished build + + + +Time Elapsed 00:00:00.01 + +".Replace ("\r\n", "\n"); + var sw = new StringWriter(); + var e = new ConsoleLogger(LoggerVerbosity.Diagnostic, msg => sw.WriteLine(msg), c => {}, () => {}); + e.Verbosity = LoggerVerbosity.Diagnostic; + e.ErrorHandler (null, new BuildErrorEventArgs ("cat", "code", "file", 0, 0, 0, 0, "msg", "help", "sender")); + e.WarningHandler (null, new BuildWarningEventArgs ("cat", "code", "file", 0, 0, 0, 0, "msg", "help", "sender")); + e.ProjectStartedHandler (null, new ProjectStartedEventArgs ("start project", "HELPME", "project.txt", "target", null, null)); + e.BuildStartedHandler (null, new BuildStartedEventArgs ("start build", "HELPME", new DateTime (2013, 1, 1))); + e.TargetStartedHandler (null, new TargetStartedEventArgs ("start target", "HELPME", "target", "project.txt", "target.txt"/*, "parent"*/)); + e.TaskStartedHandler (null, new TaskStartedEventArgs ("start task", "HELPME", "project.txt", "task.txt", "task")); + e.TaskFinishedHandler (null, new TaskFinishedEventArgs ("finished task", "HELPME", "project.txt", "task.txt", "task", false)); + e.TargetFinishedHandler (null, new TargetFinishedEventArgs ("finished target", "HELPME", "target", "project.txt", "target.txt", false)); + e.ProjectFinishedHandler (null, new ProjectFinishedEventArgs ("finished project", "HELPME", "project.txt", false)); + e.BuildFinishedHandler (null, new BuildFinishedEventArgs ("finished build", "HELPME", false, new DateTime (2013, 1, 1).AddMilliseconds (1))); + + e.CustomEventHandler(null, new MyCustomBuildEventArgs ()); + Assert.AreEqual (expected, sw.ToString ().Replace ("\r\n", "\n"), "#1"); + } + } + + class MyCustomBuildEventArgs : CustomBuildEventArgs + { + } +} + diff --git a/mcs/class/Microsoft.Build/Test/Microsoft.Build.Logging/LoggerDescriptionTest.cs b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Logging/LoggerDescriptionTest.cs new file mode 100644 index 0000000000..e062fc93b4 --- /dev/null +++ b/mcs/class/Microsoft.Build/Test/Microsoft.Build.Logging/LoggerDescriptionTest.cs @@ -0,0 +1,49 @@ +// +// LoggerDescriptionTest.cs +// +// Author: +// Atsushi Eno (atsushi@xamarin.com) +// +// Copyright (C) 2013 Xamarin Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using Microsoft.Build.Logging; +using Microsoft.Build.Framework; +using NUnit.Framework; + +namespace MonoTests.Microsoft.Build.Logging +{ + [TestFixture] + public class LoggerDescriptionTest + { + [Test] + public void CreateLogger () + { + new LoggerDescription ("Microsoft.Build.Logging.ConsoleLogger", + typeof (ConsoleLogger).Assembly.FullName, + null, + null, + LoggerVerbosity.Normal) + .CreateLogger(); + } + } +} |