[xbuild] Clean up test logs.
[mono.git] / mcs / class / Microsoft.Build.Engine / Test / various / Items.cs
old mode 100644 (file)
new mode 100755 (executable)
index 852afd0..5f6863b
@@ -32,6 +32,8 @@ using System.Text;
 using System.Xml;
 using Microsoft.Build.BuildEngine;
 using NUnit.Framework;
+using System.IO;
+using Microsoft.Build.Framework;
 
 namespace MonoTests.Microsoft.Build.BuildEngine.Various {
        [TestFixture]
@@ -131,6 +133,120 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        CheckItems (proj, "Item3", "A2", "AxxBxxC");
                }
 
+               [Test]
+               // item with 1. item ref with a separator and 2. another item ref
+               public void TestItems2a () {
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+
+                       string documentString = @"
+                               <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+                                       <ItemGroup>
+                                               <Item0 Include='D'/>
+                                               <Item1 Include='A;B;C' />
+                                               <Item2 Include=""@(Item1,'-');@(Item0)"" />
+                                               <Item3 Include=""@(Item1,'xx')"" />
+                                       </ItemGroup>
+                               </Project>
+                       ";
+
+                       proj.LoadXml (documentString);
+
+                       CheckItems (proj, "Item2", "A1", "A-B-C", "D");
+                       CheckItems (proj, "Item3", "A2", "AxxBxxC");
+               }
+
+               [Test]
+               public void TestInheritedMetadataFromItemRefs () {
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       engine.RegisterLogger (logger);
+
+                       string documentString = @"
+                               <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+                                       <ItemGroup>
+                                               <Item0 Include='D'>
+                                                       <MD0>Val0</MD0>
+                                               </Item0>
+                                               <Item1 Include='A;@(Item0)' >
+                                                       <MD1>Val1</MD1>
+                                               </Item1>
+                                               <Item2 Include=""@(Item1,'-')"" />
+                                               <Item3 Include=""@(Item1);Z"" />
+                                       </ItemGroup>
+
+                                               <Target Name=""Main"">
+               <Message Text=""Item2: %(Item2.Identity) MD0: %(Item2.MD0) MD1: %(Item2.MD1)""/>
+               <Message Text=""Item3: %(Item3.Identity) MD0: %(Item3.MD0) MD1: %(Item3.MD1)""/>
+       </Target>
+                               </Project>
+                       ";
+
+                       proj.LoadXml (documentString);
+
+                       CheckItems (proj, "Item2", "A1", "A-D");
+                       CheckItems (proj, "Item3", "A2", "A", "D", "Z");
+
+                       if (!proj.Build ("Main")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("Item2: A-D MD0:  MD1: ", "A4");
+
+                       logger.CheckLoggedMessageHead ("Item3: A MD0:  MD1: Val1", "A5");
+                       logger.CheckLoggedMessageHead ("Item3: D MD0: Val0 MD1: Val1", "A6");
+                       logger.CheckLoggedMessageHead ("Item3: Z MD0:  MD1: ", "A7");
+
+                       Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
+               }
+
+               [Test]
+               public void TestInheritedMetadataFromItemRefs2 () {
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       engine.RegisterLogger (logger);
+
+                       string documentString = @"
+                               <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+                                       <ItemGroup>
+                                               <Item5 Include='ZZ'>
+                                                       <MD5>Val5</MD5>
+                                               </Item5>
+
+                                               <Item0 Include='D'>
+                                                       <MD0>Val0</MD0>
+                                               </Item0>
+                                               <Item1 Include='A;@(Item0)' >
+                                                       <MD1>Val1</MD1>
+                                               </Item1>
+                                               <Item2 Include=""@(Item1,'-');@(Item5)"" />
+                                       </ItemGroup>
+
+                                               <Target Name=""Main"">
+               <Message Text=""Item2: %(Item2.Identity) MD0: %(Item2.MD0) MD1: %(Item2.MD1) MD5: %(Item2.MD5)""/>
+       </Target>
+                               </Project>
+                       ";
+
+                       proj.LoadXml (documentString);
+
+                       CheckItems (proj, "Item2", "A1", "A-D", "ZZ");
+
+                       if (!proj.Build ("Main")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("Item2: A-D MD0:  MD1:  MD5: ", "A4");
+                       logger.CheckLoggedMessageHead ("Item2: ZZ MD0:  MD1:  MD5: Val5", "A5");
+                       Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
+               }
+
                [Test]
                public void TestItems3 ()
                {
@@ -160,29 +276,41 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
 
                        string documentString = @"
                                <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <PropertyGroup>
+                                               <Prop1>@(Item0)</Prop1>
+                                       </PropertyGroup>
                                        <ItemGroup>
+                                               <Item0 Include=""Foo""/>
                                                <Item1 Include='A;B;C' />
                                                <Item2 Include=""A\B.txt;A\C.txt;B\B.zip;B\C.zip"" />
+                                               <ItemT0 Include=""@(Item1)"" />
                                                <ItemT1 Include=""@(Item1->'%(Identity)')"" />
                                                <ItemT2 Include=""@(Item1->'%(Identity)%(Identity)')"" />
                                                <ItemT3 Include=""@(Item1->'(-%(Identity)-)')"" />
                                                <ItemT4 Include=""@(Item2->'%(Extension)')"" />
                                                <ItemT5 Include=""@(Item2->'%(Filename)/%(Extension)')"" />
+                                               <ItemT6 Include=""@(Item2->'%(Extension)/$(Prop1)')"" />
                                        </ItemGroup>
                                </Project>
                        ";
 
                        proj.LoadXml (documentString);
 
+                       //Assert.IsTrue (proj.Build (), "Build failed");
+
+                       Assert.AreEqual ("@(Item0)", proj.EvaluatedProperties["Prop1"].FinalValue, "A0");
+                       //Assert.AreEqual ("@(Item2->'%(Extension)/$(Prop1)')", proj.EvaluatedItems [7].FinalItemSpec, "B0");
+
+                       CheckItems (proj, "ItemT0", "A1", "A", "B", "C");
                        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");
+                       CheckItems (proj, "ItemT6", "A6", ".txt/@(Item0)", ".txt/@(Item0)", ".zip/@(Item0)", ".zip/@(Item0)");
                }
 
                [Test]
-               [Category ("NotWorking")]
                public void TestItems5 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -192,18 +320,20 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                                <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
                                        <ItemGroup>
                                                <Item Include=""A\B.txt;A\C.txt;B\B.zip;B\C.zip"" />
-                                               <ItemT Include=""@(Item->'%(RelativeDir)X/%(Filename)')"" />
+                                               <ItemT Include=""@(Item->'%(RelativeDir)X\%(Filename)')"" />
                                        </ItemGroup>
                                </Project>
                        ";
 
                        proj.LoadXml (documentString);
 
-                       CheckItems (proj, "ItemT", "A1", @"A\X/B", @"A\X/C", @"B\X/B", @"B\X/C");
+                       string dir_a = Path.Combine ("A", "X");
+                       string dir_b = Path.Combine ("B", "X");
+                       CheckItems (proj, "ItemT", "A1", Path.Combine (dir_a, "B"), Path.Combine (dir_a, "C"),
+                                                               Path.Combine (dir_b, "B"), Path.Combine (dir_b, "C"));
                }
 
                [Test]
-               [Category ("NotWorking")]
                public void TestItems6 ()
                {
                        Engine engine = new Engine (Consts.BinPath);
@@ -237,11 +367,11 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        CheckItems (proj, "Item7", "A6", "A", "B", "C");
                }
 
+               // 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.
                [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.  ")]
+               [ExpectedException (typeof (InvalidProjectFileException))]
                [Category ("NotWorking")]
                public void TestItems7 ()
                {
@@ -260,11 +390,11 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        proj.LoadXml (documentString);
                }
 
+               // 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.
                [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.  ")]
+               [ExpectedException (typeof (InvalidProjectFileException))]
                [Category ("NotWorking")]
                public void TestItems8 ()
                {
@@ -283,11 +413,11 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        proj.LoadXml (documentString);
                }
 
+               // 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.
                [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.  ")]
+               [ExpectedException (typeof (InvalidProjectFileException))]
                [Category ("NotWorking")]
                public void TestItems9 ()
                {
@@ -306,6 +436,368 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        proj.LoadXml (documentString);
                }
 
+               [Test]
+               // test item metadata
+               public void TestItems10 ()
+               {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+       <PropertyGroup>
+               <Prop1>@(Item0)</Prop1>
+               <Prop2>@(Ref1)</Prop2>
+       </PropertyGroup>
+       <ItemGroup>
+               <Item0 Include=""Foo""/>
+               <Ref1 Include=""File1"" />
+               <IWithM Include=""A"">
+                       <Md>@(Item0)</Md>
+                       <Md2>$(Prop2)</Md2>
+               </IWithM>
+       </ItemGroup>
+
+       <Target Name=""1"">
+               <Message Text=""IWithM.md: %(IWithM.Md)""/>
+               <Message Text=""IWithM.md2: %(IWithM.Md2)""/>
+
+               <CreateItem Include=""Bar;Xyz"">
+                       <Output TaskParameter=""Include"" ItemName=""Item0""/>
+               </CreateItem>
+               
+               <Message Text=""IWithM.md: %(IWithM.Md)""/>
+               <Message Text=""IWithM.md2: %(IWithM.Md2)""/>
+       </Target>
+</Project>
+";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("IWithM.md: Foo", "A1");
+                       logger.CheckLoggedMessageHead ("IWithM.md2: File1", "A2");
+
+                       logger.CheckLoggedMessageHead ("IWithM.md: Foo", "A3");
+                       logger.CheckLoggedMessageHead ("IWithM.md2: File1", "A4");
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
+               [Test]
+               // Test Item/prop references in conditions
+               public void TestItems11 () {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+       <PropertyGroup>
+               <Prop1>@(Item0)</Prop1>
+       </PropertyGroup>
+       <ItemGroup>
+               <Item0 Include=""Foo""/>
+               <Item1 Include=""@(Item0)""/>
+
+               <CondItem Condition=""'@(Item1)' == '@(Item0)'"" Include=""Equal to item0""/>
+               <CondItem Condition=""'@(Item1)' == 'Foo'"" Include=""Equal to item0's value""/>
+
+               <CondItem1 Condition=""'$(Prop1)' == '@(Item0)'"" Include=""Equal to item0""/>
+               <CondItem1 Condition=""'$(Prop1)' == 'Foo'"" Include=""Equal to item0's value""/>
+       </ItemGroup>
+
+       <Target Name=""1"">
+               <Message Text = ""CondItem: %(CondItem.Identity)""/>
+               <Message Text = ""CondItem1: %(CondItem1.Identity)""/>
+       </Target>
+</Project>
+";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("CondItem: Equal to item0", "A1");
+                       logger.CheckLoggedMessageHead ("CondItem: Equal to item0's value", "A2");
+                       logger.CheckLoggedMessageHead ("CondItem1: Equal to item0", "A3");
+                       logger.CheckLoggedMessageHead ("CondItem1: Equal to item0's value", "A4");
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
+               [Test]
+               // test properties and item refs, with dynamic properties/items
+               public void TestItems12 ()
+               {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+       <PropertyGroup>
+               <Prop2>@(Ref1)</Prop2>
+       </PropertyGroup>
+       <ItemGroup>
+               <Ref1 Include=""File1"" />
+               <Files Include=""@(Ref1)""/>
+       </ItemGroup>
+
+       <Target Name=""1"">
+               <Message Text=""Prop2: $(Prop2)""/>
+               
+               <Message Text=""Files: @(Files)""/>
+               <CreateItem Include=""foobar"">
+                       <Output TaskParameter=""Include"" ItemName=""Ref1""/>
+               </CreateItem>
+               <Message Text=""Files: @(Files)""/>
+
+               <Message Text=""Prop2: $(Prop2)""/>
+               <CreateProperty Value=""NewValue"">
+                       <Output TaskParameter=""Value"" PropertyName=""Prop2""/>
+               </CreateProperty>
+               <Message Text=""Prop2: $(Prop2)""/>
+       </Target>
+</Project>
+";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("Prop2: File1", "A1");
+                       logger.CheckLoggedMessageHead ("Files: File1", "A1");
+                       logger.CheckLoggedMessageHead ("Files: File1", "A1");
+                       logger.CheckLoggedMessageHead ("Prop2: File1;foobar", "A1");
+                       logger.CheckLoggedMessageHead ("Prop2: NewValue", "A1");
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
+               [Test]
+               // test item refs in properties
+               public void TestItems13 () {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+       <PropertyGroup>
+               <Prop1>@(Item0)</Prop1>
+       </PropertyGroup>
+       <ItemGroup>
+               <Item0 Include=""Foo""/>
+               <Item1 Include=""A\B.txt;A\C.txt;B\B.zip;B\C.zip"" />
+               <Item2 Include=""@(Item1->'%(Extension)/$(Prop1)')"" />
+       </ItemGroup>
+
+       <Target Name='1'>
+               <Message Text=""Item2: @(Item2)""/>
+       </Target>
+</Project>";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("Item2: .txt/@(Item0);.txt/@(Item0);.zip/@(Item0);.zip/@(Item0)", "A1");
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
+               [Test]
+               public void TestMetadataFromItemReferences () {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+       <ItemGroup>
+               <Item1 Include=""Item1Val1;Item1Val2"">
+                       <Item1Md>False</Item1Md>
+               </Item1>
+               <Item2 Include=""Val1;Val2;@(Item1);Val3"">
+                       <Name>Random name</Name>
+               </Item2>
+               <Item3 Include=""foo;bar;@(Item2);Last""/>
+       </ItemGroup>
+
+       <Target Name=""Main"">
+               <CreateItem Include=""@(Item3)"">
+                       <Output TaskParameter=""Include""  ItemName=""Final""/>
+               </CreateItem>
+
+               <Message Text=""Final: %(Final.Identity) Item1Md: %(Final.Item1Md) Name: %(Final.Name)""/>
+       </Target>
+</Project>";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("Main")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       CheckItems (proj, "Final", "Z", "foo", "bar", "Val1", "Val2", "Item1Val1", "Item1Val2", "Val3", "Last");
+
+                       logger.CheckLoggedMessageHead ("Final: foo Item1Md:  Name: ", "A1");
+                       logger.CheckLoggedMessageHead ("Final: bar Item1Md:  Name: ", "A2");
+                       logger.CheckLoggedMessageHead ("Final: Val1 Item1Md:  Name: Random name", "A3");
+                       logger.CheckLoggedMessageHead ("Final: Val2 Item1Md:  Name: Random name", "A4");
+                       logger.CheckLoggedMessageHead ("Final: Item1Val1 Item1Md: False Name: Random name", "A5");
+                       logger.CheckLoggedMessageHead ("Final: Item1Val2 Item1Md: False Name: Random name", "A6");
+                       logger.CheckLoggedMessageHead ("Final: Val3 Item1Md:  Name: Random name", "A7");
+                       logger.CheckLoggedMessageHead ("Final: Last Item1Md:  Name: ", "A8");
+
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
+               [Test]
+               public void TestSelfRefrentialItems ()
+               {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+       <PropertyGroup>
+               <Prop1>@(Item1);Val</Prop1>
+               <Prop2>@(Item2)</Prop2>
+               <Prop3>@(Item3)</Prop3>
+       </PropertyGroup>
+       <ItemGroup>
+               <Item1 Include=""Item1OldVal""/>
+               <Item1 Include=""@(Item1);$(Prop1)""/>
+
+               <Item2 Include=""Item2OldVal""/>
+               <Item2 Include=""@(Item2->'%(Identity)');$(Prop2)""/>
+
+               <Item3 Include=""Item3OldVal""/>
+               <Item3 Include=""@(Item3, '_');$(Prop3)""/>
+
+               <Item4 Include=""@(Item4)""/>
+       </ItemGroup>
+
+       <Target Name=""1"">
+               <Message Text=""Item1: %(Item1.Identity)""/>
+               <Message Text=""Item2: %(Item2.Identity)""/>
+               <Message Text=""Item3: %(Item3.Identity)""/>
+               <Message Text=""%(Item4.Identity)""/>
+               <Message Text=""Item4: %(Item4.Identity)""/>
+       </Target>
+</Project>
+";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("Item1: Item1OldVal", "A1");
+                       logger.CheckLoggedMessageHead ("Item1: Val", "A2");
+                       logger.CheckLoggedMessageHead ("Item2: Item2OldVal", "A3");
+                       logger.CheckLoggedMessageHead ("Item3: Item3OldVal", "A4");
+                       logger.CheckLoggedMessageHead ("Item4: ", "A5");
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
+               [Test]
+               public void TestEmptyItemsWithBatching ()
+               {
+                       string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                       <UsingTask TaskName='StringTestTask' AssemblyFile='Test\resources\TestTasks.dll' />
+                       <UsingTask TaskName='TestTask_TaskItem' AssemblyFile='Test\resources\TestTasks.dll' />
+                       <UsingTask TaskName='TestTask_TaskItems' AssemblyFile='Test\resources\TestTasks.dll' />
+       <Target Name=""1"">
+               <StringTestTask Property=""%(Item4.Identity)"">
+                       <Output TaskParameter=""OutputString"" PropertyName=""OutputString""/>
+               </StringTestTask>
+               <Message Text='output1: $(OutputString)'/>
+
+               <StringTestTask Property=""  %(Item4.Identity)"">
+                       <Output TaskParameter=""OutputString"" PropertyName=""OutputString""/>
+               </StringTestTask>
+               <Message Text='output2: $(OutputString)'/>
+
+               <StringTestTask Array=""%(Item4.Identity)"">
+                       <Output TaskParameter=""OutputString"" PropertyName=""OutputString""/>
+               </StringTestTask>
+               <Message Text='output3: $(OutputString)'/>
+
+               <StringTestTask Array=""  %(Item4.Identity)"">
+                       <Output TaskParameter=""OutputString"" PropertyName=""OutputString""/>
+               </StringTestTask>
+               <Message Text='output4: $(OutputString)'/>
+
+
+               <TestTask_TaskItem Property=""%(Item4.Identity)"">
+                       <Output TaskParameter=""Output"" PropertyName=""OutputString""/>
+               </TestTask_TaskItem>
+               <Message Text='output5: $(OutputString)'/>
+
+               <TestTask_TaskItem Property=""  %(Item4.Identity)"">
+                       <Output TaskParameter=""Output"" PropertyName=""OutputString""/>
+               </TestTask_TaskItem>
+               <Message Text='output6: $(OutputString)'/>
+
+
+               <TestTask_TaskItems Property=""  %(Item4.Identity)"">
+                       <Output TaskParameter=""Output"" PropertyName=""OutputString""/>
+               </TestTask_TaskItems>
+               <Message Text='output7: $(OutputString)'/>
+       
+
+               <!-- no space in property -->
+               <TestTask_TaskItems Property=""%(Item4.Identity)"">
+                       <Output TaskParameter=""Output"" PropertyName=""OutputString""/>
+               </TestTask_TaskItems>
+               <Message Text='output8: $(OutputString)'/>
+
+       </Target>
+</Project>
+";
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       proj.LoadXml (project_xml);
+                       engine.RegisterLogger (logger);
+
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("output1: property: null ## array: null", "A1");
+                       logger.CheckLoggedMessageHead ("output2: property:    ## array: null", "A2");
+                       logger.CheckLoggedMessageHead ("output3: property: null ## array: null", "A3");
+                       logger.CheckLoggedMessageHead ("output4: property: null ## array: null", "A4");
+
+                       logger.CheckLoggedMessageHead ("output5: null", "A5");
+                       logger.CheckLoggedMessageHead ("output6: null", "A6");
+                       logger.CheckLoggedMessageHead ("output7: null", "A7");
+                       logger.CheckLoggedMessageHead ("output8: null", "A8");
+
+                       Assert.AreEqual (0, logger.NormalMessageCount, "unexpected messages found");
+               }
+
                [Test]
                public void TestItemsInTarget1 ()
                {
@@ -317,6 +809,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                                        <UsingTask TaskName='StringTestTask' AssemblyFile='Test\resources\TestTasks.dll' />
                                        <PropertyGroup>
                                                <A>A</A>
+                                               <B>@(A)g</B>
                                        </PropertyGroup>
                                        <ItemGroup>
                                                <A Include='A;B;C' />
@@ -338,6 +831,9 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                                                <StringTestTask Property=""@(A,'@(A,'')')"">
                                                        <Output TaskParameter='Property' PropertyName='P5' />
                                                </StringTestTask>
+                                               <StringTestTask Property=""@(A,'$(B)')"">
+                                                       <Output TaskParameter='Property' PropertyName='P6' />
+                                               </StringTestTask>
                                                <StringTestTask Property=""%(A.Filename)"">
                                                        <Output TaskParameter='Property' ItemName='I1' />
                                                </StringTestTask>
@@ -348,18 +844,26 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                                </Project>
                        ";
 
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger = new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       engine.RegisterLogger (logger);
                        proj.LoadXml (documentString);
-                       Assert.IsTrue (proj.Build ("1"), "A0, Build failed");
+                       if (!proj.Build ("1")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("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");
+                       Assert.AreEqual ("A@(A)gB@(A)gC", proj.GetEvaluatedProperty ("P6"), "A6");
                        CheckItems (proj, "I1", "A6", "A", "B", "C");
                        CheckItems (proj, "I2", "A7", "A A", "B B", "C C");
                }
 
+
+
                [Test]
                [Category ("NotWorking")]
                public void TestItemsInTarget2 ()
@@ -459,6 +963,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                                                "  $(C)   Foo    $(C)  Bar ; $(B)   ",
                                                "@(A);$(C)",
                                                "@(A);A;B;C",
+                                               "  abc;  @(A)  ;  $(C)  ;foo",
                                        }) + "</Project>";
 
 
@@ -473,6 +978,7 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        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");
+                       CheckItems(proj, "I8", "A8", "abc", "A", "B", "C", "A", "foo");
                }
 
                [Test]
@@ -523,6 +1029,9 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                {
                        Engine engine = new Engine (Consts.BinPath);
                        Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger();
+                       engine.RegisterLogger(logger);
 
                        string documentString = @"
                                <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
@@ -546,11 +1055,14 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                                                "$(C) $(C)",
                                                "@(A);$(C)",
                                                "@(A);A;B;C",
-                                               "@(A) $(C) @(A)"
+                                               "@(A) $(C) @(A)",
                                        }) + "</Project>";
 
                        proj.LoadXml (documentString);
-                       Assert.IsTrue (proj.Build ("1"), "Build failed");
+                       if (!proj.Build("1")) {
+                               logger.DumpMessages();
+                               Assert.Fail("Build failed");
+                       }
 
                        BuildProperty bp = proj.EvaluatedProperties ["D"];
                        Assert.AreEqual ("$(C);Foo", bp.Value, "B0");
@@ -878,5 +1390,141 @@ namespace MonoTests.Microsoft.Build.BuildEngine.Various {
                        Assert.AreEqual ("True", bi.GetMetadata ("M"), "A10");
                        Assert.AreEqual ("True", bi.GetEvaluatedMetadata ("M"), "A11");*/
                }
+
+               [Test]
+               public void TestItemsWithWildcards ()
+               {
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       engine.RegisterLogger (logger);
+
+                       // Setup
+
+                       string basedir = PathCombine ("Test", "resources", "dir");
+                       string aaa = PathCombine ("a", "aa", "aaa");
+                       string bb = Path.Combine ("b", "bb");
+
+                       string[] dirs = { aaa, bb, "c" };
+                       string [] files = {
+                                                               PathCombine (basedir, aaa, "foo.dll"),
+                                                               PathCombine (basedir, bb, "bar.dll"),
+                                                               PathCombine (basedir, bb, "sample.txt"),
+                                                               Path.Combine (basedir, "xyz.dll")
+                                                         };
+
+                       string documentString = @"
+                               <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup>
+                                               <ItemsRel Include='dir\**\*.dll' Exclude='*\x*.dll' />
+                                               <ItemsRelExpanded Include=""@(ItemsRel->'%(FullPath)')"" />
+                                               <ItemsAbs Include='$(MSBuildProjectDirectory)\dir\**\*.dll'/>
+                                       </ItemGroup>
+
+                                       <Target Name='Main'>
+                                               <Message Text=""ItemsRel: %(ItemsRel.FullPath) RecDir: %(ItemsRel.RecursiveDir)""/>
+                                               <Message Text=""ItemsRelExpanded: %(ItemsRelExpanded.Identity)""/>
+                                               <Message Text='ItemsAbs: %(ItemsAbs.Identity) RecDir: %(ItemsAbs.RecursiveDir)'/>
+                                       </Target>
+                               </Project>";
+
+                       try {
+                               CreateDirectoriesAndFiles (basedir, dirs, files);
+                               string projectdir = Path.Combine ("Test", "resources");
+                               File.WriteAllText (Path.Combine (projectdir, "wild1.proj"), documentString);
+                               proj.Load (Path.Combine (projectdir, "wild1.proj"));
+                               if (!proj.Build ("Main")) {
+                                       logger.DumpMessages ();
+                                       Assert.Fail ("Build failed");
+                               }
+                               string full_base_dir = Path.GetFullPath (basedir);
+
+                               logger.CheckLoggedAny (@"ItemsRel: "+ PathCombine (full_base_dir, aaa, "foo.dll") +
+                                                       " RecDir: " + aaa + Path.DirectorySeparatorChar, MessageImportance.Normal, "A1");
+
+                               logger.CheckLoggedAny (@"ItemsRel: " + PathCombine (full_base_dir, bb, "bar.dll") +
+                                                       " RecDir: " + bb + Path.DirectorySeparatorChar, MessageImportance.Normal, "A2");
+
+                               logger.CheckLoggedAny (@"ItemsRelExpanded: " + PathCombine (full_base_dir, aaa, "foo.dll"), MessageImportance.Normal, "A3");
+                               logger.CheckLoggedAny (@"ItemsRelExpanded: " + PathCombine (full_base_dir, bb, "bar.dll"), MessageImportance.Normal, "A4");
+
+                               logger.CheckLoggedAny (@"ItemsAbs: " + PathCombine (full_base_dir, aaa, "foo.dll") +
+                                                       @" RecDir: " + aaa + Path.DirectorySeparatorChar, MessageImportance.Normal, "A5");
+                               logger.CheckLoggedAny (@"ItemsAbs: " + PathCombine (full_base_dir, bb, "bar.dll") +
+                                                       @" RecDir: " + bb + Path.DirectorySeparatorChar, MessageImportance.Normal, "A6");
+                               logger.CheckLoggedAny (@"ItemsAbs: " + PathCombine (full_base_dir, "xyz.dll") +
+                                                       @" RecDir: ", MessageImportance.Normal, "A7");
+
+                               Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
+                       } catch (AssertionException) {
+                               logger.DumpMessages ();
+                               throw;
+                       } finally {
+                               Directory.Delete (basedir, true);
+                       }
+               }
+
+               [Test]
+               public void TestReservedMetadata ()
+               {
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project proj = engine.CreateNewProject ();
+                       MonoTests.Microsoft.Build.Tasks.TestMessageLogger logger =
+                               new MonoTests.Microsoft.Build.Tasks.TestMessageLogger ();
+                       engine.RegisterLogger (logger);
+
+                       string documentString = @"
+                               <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+                                       <ItemGroup><File1 Include=""bar\foo.dll""/></ItemGroup>
+                                       <Target Name='Main'>
+                                               <Message Text='file1: @(File1)'/>
+                                               <Message Text='file1: RootDir: %(File1.RootDir)'/>
+                                               <Message Text='file1: Directory: %(File1.Directory)'/>
+                                       </Target>
+                               </Project>";
+
+                       string projectdir = Path.Combine ("Test", "resources");
+                       File.WriteAllText (Path.Combine (projectdir, "test1.proj"), documentString);
+                       proj.Load (Path.Combine (projectdir, "test1.proj"));
+                       if (!proj.Build ("Main")) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Build failed");
+                       }
+
+                       logger.CheckLoggedMessageHead ("file1: " + Path.Combine ("bar", "foo.dll"), "A1");
+
+                       string path_root = Path.GetPathRoot (Path.GetFullPath (projectdir));
+                       logger.CheckLoggedMessageHead ("file1: RootDir: " + path_root, "A2");
+
+                       string fullpath = Path.GetFullPath (Path.Combine (projectdir, "bar"));
+                       logger.CheckLoggedMessageHead ("file1: Directory: " + fullpath.Substring (path_root.Length) + Path.DirectorySeparatorChar, "A3");
+
+                       if (logger.NormalMessageCount != 0) {
+                               logger.DumpMessages ();
+                               Assert.Fail ("Unexpected extra messages found");
+                       }
+               }
+
+               void CreateDirectoriesAndFiles (string basedir, string[] dirs, string[] files)
+               {
+                       foreach (string dir in dirs)
+                               Directory.CreateDirectory (Path.Combine (basedir, dir));
+
+                       foreach (string file in files)
+                               File.WriteAllText (file, String.Empty);
+               }
+
+               string PathCombine (string path1, params string[] parts)
+               {
+                       if (parts == null || parts.Length == 0)
+                               return path1;
+
+                       string final_path = path1;
+                       foreach (string part in parts)
+                               final_path = Path.Combine (final_path, part);
+
+                       return final_path;
+               }
        }
 }