// // Items.cs // // Author: // Marek Sieradzki (marek.sieradzki@gmail.com) // Ankit Jain (jankit@novell.com) // // (C) 2006 Marek Sieradzki // Copyright 2009 Novell, Inc (http://www.novell.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.Text; using System.Xml; using Microsoft.Build.BuildEngine; using NUnit.Framework; namespace MonoTests.Microsoft.Build.BuildEngine.Various { [TestFixture] public class Items { private string GetItems (Project proj, string name) { BuildItemGroup big = proj.GetEvaluatedItemsByName (name); string str = String.Empty; if (big == null) return str; foreach (BuildItem bi in big) { if (str == String.Empty) str = bi.FinalItemSpec; else str += ";" + bi.FinalItemSpec; } return str; } private void CheckItems (Project proj, string name, string prefix, params string [] values) { BuildItemGroup big = proj.GetEvaluatedItemsByName (name); if (big == null) { Assert.Fail ("{0}: Item corresponding '{1}' not found.", prefix, name); return; } if (values.Length != big.Count) { Console.Write ("Expected> "); foreach (string s in values) Console.Write ("{0}|", s); Console.WriteLine (); Console.Write ("Actual> "); foreach (BuildItem item in big) Console.Write ("{0}|", item.FinalItemSpec); Console.WriteLine (); Assert.AreEqual (values.Length, big.Count, String.Format ("{0}: Number of items", prefix)); } for (int i = 0; i < values.Length; i ++) Assert.AreEqual (values [i], big [i].FinalItemSpec, String.Format ("{0}: Item named {1}, numbered {2}", prefix, name, i)); } [Test] public void TestItems1 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); CheckItems (proj, "Item0", "A1", "A"); CheckItems (proj, "Item1", "A2", "A", "B", "C"); CheckItems (proj, "Item2", "A3", "A", "B", "C", "A", "D"); CheckItems (proj, "Item3", "A4", "B", "C", "D"); CheckItems (proj, "Item4", "A5", "Q"); CheckItems (proj, "Item5", "A6"); CheckItems (proj, "Item6", "A7", "D"); CheckItems (proj, "Item7", "A8"); } [Test] public void TestItems2 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); CheckItems (proj, "Item2", "A1", "A-B-C"); CheckItems (proj, "Item3", "A2", "AxxBxxC"); } [Test] public void TestItems3 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); CheckItems (proj, "Item2", "A1", "A-B-C"); } [Test] public void TestItems4 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" '%(Identity)')"" /> '%(Identity)%(Identity)')"" /> '(-%(Identity)-)')"" /> '%(Extension)')"" /> '%(Filename)/%(Extension)')"" /> "; proj.LoadXml (documentString); CheckItems (proj, "ItemT1", "A1", "A", "B", "C"); CheckItems (proj, "ItemT2", "A2", "AA", "BB", "CC"); CheckItems (proj, "ItemT3", "A3", "(-A-)", "(-B-)", "(-C-)"); CheckItems (proj, "ItemT4", "A4", ".txt", ".txt", ".zip", ".zip"); CheckItems (proj, "ItemT5", "A5", "B/.txt", "C/.txt", "B/.zip", "C/.zip"); } [Test] [Category ("NotWorking")] public void TestItems5 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" '%(RelativeDir)X/%(Filename)')"" /> "; proj.LoadXml (documentString); CheckItems (proj, "ItemT", "A1", @"A\X/B", @"A\X/C", @"B\X/B", @"B\X/C"); } [Test] [Category ("NotWorking")] public void TestItems6 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A '%(Filename)')"" /> "; proj.LoadXml (documentString); CheckItems (proj, "Item2", "A1", "%(A.B)"); CheckItems (proj, "Item3", "A2"); CheckItems (proj, "Item4", "A3", "AABAC"); CheckItems (proj, "Item5", "A4", "A%(A)B%(A)C"); CheckItems (proj, "Item6", "A6", "A@(A)B@(A)C"); CheckItems (proj, "Item7", "A6", "A", "B", "C"); } [Test] [ExpectedException (typeof (InvalidProjectFileException), "The expression \"@(Item1, '@(A,'')')\" cannot be used in this context. " + "Item lists cannot be concatenated with other strings where an item list is expected. " + "Use a semicolon to separate multiple item lists. ")] [Category ("NotWorking")] public void TestItems7 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); } [Test] [ExpectedException (typeof (InvalidProjectFileException), "The expression \"@(Item1, '@(A->'')')\" cannot be used in this context. " + "Item lists cannot be concatenated with other strings where an item list is expected. " + "Use a semicolon to separate multiple item lists. ")] [Category ("NotWorking")] public void TestItems8 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" '')')"" /> "; proj.LoadXml (documentString); } [Test] [ExpectedException (typeof (InvalidProjectFileException), "The expression \"@(Item1, '@(A->'','')')\" cannot be used in this context. " + "Item lists cannot be concatenated with other strings where an item list is expected. " + "Use a semicolon to separate multiple item lists. ")] [Category ("NotWorking")] public void TestItems9 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" '','')')"" /> "; proj.LoadXml (documentString); } [Test] public void TestItemsInTarget1 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A "; proj.LoadXml (documentString); Assert.IsTrue (proj.Build ("1"), "A0, Build failed"); Assert.AreEqual ("A;B;C", proj.GetEvaluatedProperty ("P1"), "A1"); Assert.AreEqual ("ABC", proj.GetEvaluatedProperty ("P2"), "A2"); Assert.AreEqual ("A@(A)B@(A)C", proj.GetEvaluatedProperty ("P3"), "A3"); Assert.AreEqual ("AABAC", proj.GetEvaluatedProperty ("P4"), "A4"); Assert.AreEqual ("@(A,'ABC')", proj.GetEvaluatedProperty ("P5"), "A5"); CheckItems (proj, "I1", "A6", "A", "B", "C"); CheckItems (proj, "I2", "A7", "A A", "B B", "C C"); } [Test] [Category ("NotWorking")] public void TestItemsInTarget2 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); Assert.IsFalse (proj.Build ("1"), "A1"); } [Test] public void TestItemsInTarget3 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A A;B A;; "; documentString += CreateTargetFragment ("StringTestTask", "Array", "Array", "I", new string [] { "$(A)$(A)", "$(B)$(B)", "$(C)", "$(C)$(C)", "@(A);$(C)", "@(A);A;B;C", "Foo;@(A)", "@(A);Foo" }) + ""; proj.LoadXml (documentString); Assert.IsTrue (proj.Build ("1"), "Build failed"); CheckItems (proj, "I0", "A0", "AA"); CheckItems (proj, "I1", "A1", "A", "BA", "B"); CheckItems (proj, "I2", "A2", "A"); CheckItems (proj, "I3", "A3", "A", "A"); CheckItems (proj, "I4", "A4", "A", "B", "C", "A"); CheckItems (proj, "I5", "A5", "A", "B", "C", "A", "B", "C"); CheckItems (proj, "I6", "A6", "Foo", "A", "B", "C"); CheckItems (proj, "I7", "A7", "A", "B", "C", "Foo"); } [Test] //Test with ITaskItem[] public void TestItemsInTarget3a () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A A;B A;; "; documentString += CreateTargetFragment ("BatchingTestTask", "Sources", "Output", "I", new string [] { "$(A)$(A)", "$(B)$(B)", "$(C)", "$(C)$(C)", "$(C) $(C)", " $(C) Foo $(C) Bar ; $(B) ", "@(A);$(C)", "@(A);A;B;C", }) + ""; proj.LoadXml (documentString); Assert.IsTrue (proj.Build ("1"), "Build failed"); CheckItems (proj, "I0", "A0", "AA"); CheckItems (proj, "I1", "A1", "A", "BA", "B"); CheckItems (proj, "I2", "A2", "A"); CheckItems (proj, "I3", "A3", "A", "A"); CheckItems (proj, "I4", "A4", "A", "A"); CheckItems (proj, "I5", "A5", "A", "Foo A", "Bar", "A", "B"); CheckItems (proj, "I6", "A6", "A", "B", "C", "A"); CheckItems (proj, "I7", "A7", "A", "B", "C", "A", "B", "C"); } [Test] //Test with string[] public void TestItemsInTarget3b () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A A;B A;; "; documentString += CreateTargetFragment ("BatchingTestTask", "Strings", "StringsOutput", "I", new string [] { "$(A)$(A)", "$(B)$(B)", "$(C)", "$(C)$(C)", "$(C) $(C) $(C)Bar$(C)", "@(A);$(C)", "@(A);A;B;C" }) + ""; proj.LoadXml (documentString); Assert.IsTrue (proj.Build ("1"), "Build failed"); CheckItems (proj, "I0", "A0", "AA"); CheckItems (proj, "I1", "A1", "A", "BA", "B"); CheckItems (proj, "I2", "A2", "A"); CheckItems (proj, "I3", "A3", "A", "A"); CheckItems (proj, "I4", "A4", "A", "A", "A", "BarA"); CheckItems (proj, "I5", "A5", "A", "B", "C", "A"); CheckItems (proj, "I6", "A6", "A", "B", "C", "A", "B", "C"); } [Test] //Test with string public void TestItemsInTarget3c () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A A;B A;; $(C);Foo "; documentString += CreateTargetFragment ("BatchingTestTask", "SingleString", "SingleStringOutput", "I", new string [] { "$(A)$(A)", "$(B)$(B)", "$(C)", "$(C)$(C)", "$(C) $(C)", "@(A);$(C)", "@(A);A;B;C", "@(A) $(C) @(A)" }) + ""; proj.LoadXml (documentString); Assert.IsTrue (proj.Build ("1"), "Build failed"); BuildProperty bp = proj.EvaluatedProperties ["D"]; Assert.AreEqual ("$(C);Foo", bp.Value, "B0"); Assert.AreEqual ("A;;;Foo", bp.FinalValue, "B1"); bp = proj.EvaluatedProperties ["C"]; Assert.AreEqual ("A;;", bp.Value, "B3"); Assert.AreEqual ("A;;", bp.FinalValue, "B4"); CheckItems (proj, "I0", "A0", "AA"); CheckItems (proj, "I1", "A1", "A;BA;B"); CheckItems (proj, "I2", "A2", "A;;"); CheckItems (proj, "I3", "A3", "A;;A;;"); CheckItems (proj, "I4", "A4", "A;; A;;"); CheckItems (proj, "I5", "A5", "A;B;C;A;;"); CheckItems (proj, "I6", "A6", "A;B;C;A;B;C"); CheckItems (proj, "I7", "A7", "A;B;C A;; A;B;C"); } [Test] public void TestSingleTaskItemError1 () { CheckSingleTaskItemProject ("$(B)$(B)"); } [Test] public void TestSingleTaskItemError2 () { CheckSingleTaskItemProject ("$(C)$(C)"); } [Test] public void TestSingleTaskItemError3 () { CheckSingleTaskItemProject ("$(C) $(C)"); } [Test] public void TestSingleTaskItemError4 () { CheckSingleTaskItemProject ("@(A)"); } [Test] public void TestSingleTaskItemError5 () { CheckSingleTaskItemProject ("@(A);$(C))"); } [Test] public void TestSingleTaskItemError6 () { CheckSingleTaskItemProject ("@(A);A;B;C"); } [Test] public void TestSingleTaskItemError7 () { CheckSingleTaskItemProject ("@(Item1)$(C)"); } [Test] public void TestSingleTaskItemError8 () { CheckSingleTaskItemProject ("$(B).foo"); } [Test] public void TestSingleTaskItem1 () { Project proj = BuildProjectForSingleTaskItem ("$(D)$(C)"); CheckItems (proj, "I0", "A0", "A"); } [Test] public void TestSingleTaskItem2 () { Project proj = BuildProjectForSingleTaskItem ("@(Item1)"); CheckItems (proj, "I0", "A0", "F"); } [Test] public void TestSingleTaskItem3 () { Project proj = BuildProjectForSingleTaskItem ("$(A).foo"); CheckItems (proj, "I0", "A0", "A.foo"); } [Test] public void TestSingleTaskItem4 () { Project proj = BuildProjectForSingleTaskItem ("$(C)"); CheckItems (proj, "I0", "A0", "A"); } void CheckSingleTaskItemProject (string expression) { string documentString = CreateProjectForSingleTaskItem (expression); Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); proj.LoadXml (documentString); Assert.IsFalse (proj.Build ("1"), "Build should've failed"); } Project BuildProjectForSingleTaskItem (string expression) { string documentString = CreateProjectForSingleTaskItem (expression); Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); proj.LoadXml (documentString); Assert.IsTrue (proj.Build ("1"), "Build failed"); return proj; } string CreateProjectForSingleTaskItem (string expression) { return @" A A;B A;; "; } string CreateTargetFragment (string taskname, string task_param_in, string task_param_out, string item_prefix, string [] args) { StringBuilder sb = new StringBuilder (); sb.Append (""); for (int i = 0; i < args.Length; i ++) { sb.AppendFormat ("<{0} {1}='{2}'>\n", taskname, task_param_in, args [i]); sb.AppendFormat ("\t\n", task_param_out, item_prefix, i); sb.AppendFormat ("\n", taskname); } sb.Append (""); return sb.ToString (); } [Test] public void TestItemsInTarget4 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); Assert.IsFalse (proj.Build ("1")); } [Test] public void TestItemsInTarget5 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); Assert.IsFalse (proj.Build ("1")); } [Test] public void TestItemsInTarget6 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" A "; proj.LoadXml (documentString); Assert.IsFalse (proj.Build ("1")); } [Test] public void TestItemsInTarget7 () { Engine engine = new Engine (Consts.BinPath); Project proj = engine.CreateNewProject (); string documentString = @" "; proj.LoadXml (documentString); Assert.IsFalse (proj.Build ("1")); } } }