1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 using System; 5 using System.Collections.Generic; 6 using System.IO; 7 using System.Linq; 8 using System.Reflection; 9 10 using Microsoft.Build.UnitTests; 11 12 using Microsoft.Build.Construction; 13 using Microsoft.Build.Evaluation; 14 using Microsoft.Build.Execution; 15 using Microsoft.Build.Framework; 16 using Microsoft.Build.Utilities; 17 18 19 20 using EscapingUtilities = Microsoft.Build.Shared.EscapingUtilities; 21 using FileUtilities = Microsoft.Build.Shared.FileUtilities; 22 using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException; 23 using ResourceUtilities = Microsoft.Build.Shared.ResourceUtilities; 24 using Xunit; 25 26 namespace Microsoft.Build.UnitTests.EscapingInProjects_Tests 27 { 28 /// <summary> 29 /// Test task that just logs the parameters it receives. 30 /// </summary> 31 public class MyTestTask : Task 32 { 33 private ITaskItem _taskItemParam; 34 public ITaskItem TaskItemParam 35 { 36 get 37 { 38 return _taskItemParam; 39 } 40 41 set 42 { 43 _taskItemParam = value; 44 } 45 } 46 Execute()47 override public bool Execute() 48 { 49 if (TaskItemParam != null) 50 { 51 Log.LogMessageFromText("Received TaskItemParam: " + TaskItemParam.ItemSpec, MessageImportance.High); 52 } 53 54 return true; 55 } 56 } 57 58 public class SimpleScenarios : IDisposable 59 { 60 /// <summary> 61 /// Since we create a project with the same name in many of these tests, and two projects with 62 /// the same name cannot be loaded in a ProjectCollection at the same time, we should unload the 63 /// GlobalProjectCollection (into which all of these projects are placed by default) after each test. 64 /// </summary> Dispose()65 public void Dispose() 66 { 67 ProjectCollection.GlobalProjectCollection.UnloadAllProjects(); 68 } 69 70 /// <summary> 71 /// Make sure I can define a property with escaped characters and pass it into 72 /// a string parameter of a task, in this case the Message task. 73 /// </summary> 74 [Fact] SemicolonInPropertyPassedIntoStringParam()75 public void SemicolonInPropertyPassedIntoStringParam() 76 { 77 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(@" 78 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 79 <PropertyGroup> 80 <MyPropertyWithSemicolons>abc %3b def %3b ghi</MyPropertyWithSemicolons> 81 </PropertyGroup> 82 <Target Name=`Build`> 83 <Message Text=`Property value is '$(MyPropertyWithSemicolons)'` /> 84 </Target> 85 </Project> 86 "); 87 88 logger.AssertLogContains("Property value is 'abc ; def ; ghi'"); 89 } 90 91 #if FEATURE_TASKHOST 92 /// <summary> 93 /// Make sure I can define a property with escaped characters and pass it into 94 /// a string parameter of a task, in this case the Message task. 95 /// </summary> 96 [Fact] 97 [Trait("Category", "mono-osx-failing")] SemicolonInPropertyPassedIntoStringParam_UsingTaskHost()98 public void SemicolonInPropertyPassedIntoStringParam_UsingTaskHost() 99 { 100 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(@" 101 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 102 <UsingTask TaskName=`Message` AssemblyFile=`$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll` TaskFactory=`TaskHostFactory` /> 103 <PropertyGroup> 104 <MyPropertyWithSemicolons>abc %3b def %3b ghi</MyPropertyWithSemicolons> 105 </PropertyGroup> 106 <Target Name=`Build`> 107 <Message Text=`Property value is '$(MyPropertyWithSemicolons)'` /> 108 </Target> 109 </Project> 110 "); 111 112 logger.AssertLogContains("Property value is 'abc ; def ; ghi'"); 113 } 114 #endif 115 116 #if FEATURE_ASSEMBLY_LOCATION 117 /// <summary> 118 /// Make sure I can define a property with escaped characters and pass it into 119 /// an ITaskItem[] task parameter. 120 /// </summary> 121 [Fact] SemicolonInPropertyPassedIntoITaskItemParam()122 public void SemicolonInPropertyPassedIntoITaskItemParam() 123 { 124 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(String.Format(@" 125 126 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 127 128 <UsingTask TaskName=`Microsoft.Build.UnitTests.EscapingInProjects_Tests.MyTestTask` AssemblyFile=`{0}` /> 129 130 <PropertyGroup> 131 <MyPropertyWithSemicolons>abc %3b def %3b ghi</MyPropertyWithSemicolons> 132 </PropertyGroup> 133 134 <Target Name=`Build`> 135 <MyTestTask TaskItemParam=`123 $(MyPropertyWithSemicolons) 789` /> 136 </Target> 137 138 </Project> 139 140 ", new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath)); 141 142 logger.AssertLogContains("Received TaskItemParam: 123 abc ; def ; ghi 789"); 143 } 144 145 /// <summary> 146 /// Make sure I can define a property with escaped characters and pass it into 147 /// an ITaskItem[] task parameter. 148 /// </summary> 149 [Fact] 150 [Trait("Category", "mono-osx-failing")] SemicolonInPropertyPassedIntoITaskItemParam_UsingTaskHost()151 public void SemicolonInPropertyPassedIntoITaskItemParam_UsingTaskHost() 152 { 153 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(String.Format(@" 154 155 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 156 157 <UsingTask TaskName=`Microsoft.Build.UnitTests.EscapingInProjects_Tests.MyTestTask` AssemblyFile=`{0}` TaskFactory=`TaskHostFactory` /> 158 159 <PropertyGroup> 160 <MyPropertyWithSemicolons>abc %3b def %3b ghi</MyPropertyWithSemicolons> 161 </PropertyGroup> 162 163 <Target Name=`Build`> 164 <MyTestTask TaskItemParam=`123 $(MyPropertyWithSemicolons) 789` /> 165 </Target> 166 167 </Project> 168 169 ", new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath)); 170 171 logger.AssertLogContains("Received TaskItemParam: 123 abc ; def ; ghi 789"); 172 } 173 #endif 174 175 /// <summary> 176 /// If I try to add a new item to a project, and my new item's Include has an unescaped semicolon 177 /// in it, then we shouldn't try to match it up against any existing wildcards. This is a really 178 /// bizarre scenario ... the caller probably meant to escape the semicolon. 179 /// </summary> 180 [Fact] AddNewItemWithSemicolon()181 public void AddNewItemWithSemicolon() 182 { 183 // ************************************ 184 // BEFORE 185 // ************************************ 186 string projectOriginalContents = @" 187 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 188 <ItemGroup> 189 <MyWildCard Include=`*.weirdo`/> 190 </ItemGroup> 191 </Project> 192 "; 193 194 195 // ************************************ 196 // AFTER 197 // ************************************ 198 string projectNewExpectedContents = @" 199 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 200 <ItemGroup> 201 <MyWildCard Include=`*.weirdo`/> 202 <MyWildCard Include=`foo;bar.weirdo`/> 203 </ItemGroup> 204 </Project> 205 "; 206 207 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 208 IEnumerable<ProjectItem> newItems = project.AddItem("MyWildCard", "foo;bar.weirdo"); 209 210 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 211 } 212 213 /// <summary> 214 /// If I try to add a new item to a project, and my new item's Include has a property that 215 /// contains an unescaped semicolon in it, then we shouldn't try to match it up against any existing 216 /// wildcards. 217 /// </summary> 218 [Fact] AddNewItemWithPropertyContainingSemicolon()219 public void AddNewItemWithPropertyContainingSemicolon() 220 { 221 // ************************************ 222 // BEFORE 223 // ************************************ 224 string projectOriginalContents = @" 225 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 226 <PropertyGroup> 227 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 228 </PropertyGroup> 229 <ItemGroup> 230 <MyWildCard Include=`*.weirdo`/> 231 </ItemGroup> 232 </Project> 233 "; 234 235 236 // ************************************ 237 // AFTER 238 // ************************************ 239 string projectNewExpectedContents = @" 240 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 241 <PropertyGroup> 242 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 243 </PropertyGroup> 244 <ItemGroup> 245 <MyWildCard Include=`$(FilenameWithSemicolon).weirdo`/> 246 <MyWildCard Include=`*.weirdo`/> 247 </ItemGroup> 248 </Project> 249 "; 250 251 252 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 253 IEnumerable<ProjectItem> newItems = project.AddItem("MyWildCard", "$(FilenameWithSemicolon).weirdo"); 254 255 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 256 } 257 258 /// <summary> 259 /// If I try to modify an item in a project, and my new item's Include has an unescaped semicolon 260 /// in it, then we shouldn't try to match it up against any existing wildcards. This is a really 261 /// bizarre scenario ... the caller probably meant to escape the semicolon. 262 /// </summary> 263 [Fact] ModifyItemIncludeSemicolon()264 public void ModifyItemIncludeSemicolon() 265 { 266 // ************************************ 267 // BEFORE 268 // ************************************ 269 string projectOriginalContents = @" 270 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 271 272 <ItemGroup> 273 <MyWildcard Include=`*.weirdo` /> 274 </ItemGroup> 275 276 </Project> 277 "; 278 279 280 // ************************************ 281 // AFTER 282 // ************************************ 283 string projectNewExpectedContents = @" 284 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 285 286 <ItemGroup> 287 <MyWildcard Include=`a.weirdo` /> 288 <MyWildcard Include=`foo;bar.weirdo` /> 289 <MyWildcard Include=`c.weirdo` /> 290 </ItemGroup> 291 292 </Project> 293 "; 294 295 try 296 { 297 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 298 EscapingInProjectsHelper.CreateThreeWeirdoFiles(); 299 300 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 301 302 EscapingInProjectsHelper.ModifyItemOfTypeInProject(project, "MyWildcard", "b.weirdo", "foo;bar.weirdo"); 303 304 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 305 } 306 finally 307 { 308 ObjectModelHelpers.DeleteTempProjectDirectory(); 309 } 310 } 311 312 /// <summary> 313 /// If I try to modify an item in a project, and my new item's Include has an escaped semicolon 314 /// in it, and it matches the existing wildcard, then we shouldn't need to modify the project file. 315 /// </summary> 316 [Fact] ModifyItemIncludeEscapedSemicolon()317 public void ModifyItemIncludeEscapedSemicolon() 318 { 319 // ************************************ 320 // BEFORE 321 // ************************************ 322 string projectOriginalContents = @" 323 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 324 325 <ItemGroup> 326 <MyWildcard Include=`*.weirdo` /> 327 </ItemGroup> 328 329 </Project> 330 "; 331 332 333 // ************************************ 334 // AFTER 335 // ************************************ 336 string projectNewExpectedContents = @" 337 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 338 339 <ItemGroup> 340 <MyWildcard Include=`*.weirdo` /> 341 </ItemGroup> 342 343 </Project> 344 "; 345 346 try 347 { 348 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 349 EscapingInProjectsHelper.CreateThreeWeirdoFiles(); 350 351 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 352 353 IEnumerable<ProjectItem> newItems = EscapingInProjectsHelper.ModifyItemOfTypeInProject(project, "MyWildcard", "b.weirdo", "foo%253Bbar.weirdo"); 354 355 Assert.Equal(1, newItems.Count()); 356 Assert.Equal("*.weirdo", newItems.First().UnevaluatedInclude); 357 Assert.Equal("foo%3Bbar.weirdo", newItems.First().EvaluatedInclude); 358 Assert.Equal("foo%253Bbar.weirdo", Project.GetEvaluatedItemIncludeEscaped(newItems.First())); 359 360 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 361 } 362 finally 363 { 364 ObjectModelHelpers.DeleteTempProjectDirectory(); 365 } 366 } 367 368 /// <summary> 369 /// If I try to modify an item in a project, and my new item's Include has a property that 370 /// contains an unescaped semicolon in it, then we shouldn't try to match it up against any existing 371 /// wildcards. 372 /// </summary> 373 [Fact] ModifyItemAddPropertyContainingSemicolon()374 public void ModifyItemAddPropertyContainingSemicolon() 375 { 376 // ************************************ 377 // BEFORE 378 // ************************************ 379 string projectOriginalContents = @" 380 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 381 382 <PropertyGroup> 383 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 384 </PropertyGroup> 385 386 <ItemGroup> 387 <MyWildcard Include=`*.weirdo` /> 388 </ItemGroup> 389 390 </Project> 391 "; 392 393 394 // ************************************ 395 // AFTER 396 // ************************************ 397 string projectNewExpectedContents = @" 398 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 399 400 <PropertyGroup> 401 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 402 </PropertyGroup> 403 404 <ItemGroup> 405 <MyWildcard Include=`a.weirdo` /> 406 <MyWildcard Include=`$(FilenameWithSemicolon).weirdo` /> 407 <MyWildcard Include=`c.weirdo` /> 408 </ItemGroup> 409 410 </Project> 411 "; 412 413 try 414 { 415 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 416 EscapingInProjectsHelper.CreateThreeWeirdoFiles(); 417 418 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 419 420 EscapingInProjectsHelper.ModifyItemOfTypeInProject(project, "MyWildcard", "b.weirdo", "$(FilenameWithSemicolon).weirdo"); 421 422 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 423 } 424 finally 425 { 426 ObjectModelHelpers.DeleteTempProjectDirectory(); 427 } 428 } 429 430 /// <summary> 431 /// Make sure that character escaping works as expected when adding a new item that matches 432 /// an existing wildcarded item in the project file. 433 /// </summary> 434 [Fact] AddNewItemThatMatchesWildcard1()435 public void AddNewItemThatMatchesWildcard1() 436 { 437 // ************************************ 438 // BEFORE 439 // ************************************ 440 string projectOriginalContents = @" 441 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 442 <ItemGroup> 443 <MyWildCard Include=`*.weirdo`/> 444 </ItemGroup> 445 </Project> 446 "; 447 448 449 // ************************************ 450 // AFTER 451 // ************************************ 452 string projectNewExpectedContents = @" 453 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 454 <ItemGroup> 455 <MyWildCard Include=`*.weirdo`/> 456 </ItemGroup> 457 </Project> 458 "; 459 460 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 461 IEnumerable<ProjectItem> newItems = project.AddItem("MyWildCard", "foo%253bbar.weirdo"); 462 463 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 464 465 Assert.Equal(1, newItems.Count()); 466 Assert.Equal("MyWildCard", newItems.First().ItemType); // "Newly added item should have correct ItemType" 467 Assert.Equal("*.weirdo", newItems.First().UnevaluatedInclude); // "Newly added item should have correct UnevaluatedInclude" 468 Assert.Equal("foo%253bbar.weirdo", Project.GetEvaluatedItemIncludeEscaped(newItems.First())); // "Newly added item should have correct EvaluatedIncludeEscaped" 469 Assert.Equal("foo%3bbar.weirdo", newItems.First().EvaluatedInclude); // "Newly added item should have correct EvaluatedInclude" 470 } 471 472 /// <summary> 473 /// Make sure that character escaping works as expected when adding a new item that matches 474 /// an existing wildcarded item in the project file. 475 /// </summary> 476 [Fact] AddNewItemThatMatchesWildcard2()477 public void AddNewItemThatMatchesWildcard2() 478 { 479 // ************************************ 480 // BEFORE 481 // ************************************ 482 string projectOriginalContents = @" 483 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 484 <ItemGroup> 485 <MyWildCard Include=`*.AAA%253bBBB`/> 486 </ItemGroup> 487 </Project> 488 "; 489 490 491 // ************************************ 492 // AFTER 493 // ************************************ 494 string projectNewExpectedContents = @" 495 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 496 <ItemGroup> 497 <MyWildCard Include=`*.AAA%253bBBB`/> 498 </ItemGroup> 499 </Project> 500 "; 501 502 Project project = ObjectModelHelpers.CreateInMemoryProject(projectOriginalContents); 503 IEnumerable<ProjectItem> newItems = project.AddItem("MyWildCard", "foo.AAA%253bBBB"); 504 505 Helpers.CompareProjectXml(projectNewExpectedContents, project.Xml.RawXml); 506 507 Assert.Equal(1, newItems.Count()); 508 Assert.Equal("MyWildCard", newItems.First().ItemType); // "Newly added item should have correct ItemType" 509 Assert.Equal("*.AAA%253bBBB", newItems.First().UnevaluatedInclude); // "Newly added item should have correct UnevaluatedInclude" 510 Assert.Equal("foo.AAA%253bBBB", Project.GetEvaluatedItemIncludeEscaped(newItems.First())); // "Newly added item should have correct EvaluatedIncludeEscaped" 511 Assert.Equal("foo.AAA%3bBBB", newItems.First().EvaluatedInclude); // "Newly added item should have correct EvaluatedInclude" 512 } 513 514 /// <summary> 515 /// Make sure that all inferred task outputs (those that are determined without actually 516 /// executing the task) are left escaped when they become real items in the engine, and 517 /// they only get unescaped when fed into a subsequent task. 518 /// </summary> 519 [Fact] InferEscapedOutputsFromTask()520 public void InferEscapedOutputsFromTask() 521 { 522 string inputFile = null; 523 string outputFile = null; 524 525 try 526 { 527 inputFile = FileUtilities.GetTemporaryFile(); 528 outputFile = FileUtilities.GetTemporaryFile(); 529 530 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(String.Format(@" 531 532 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 533 534 <Target Name=`GenerateResources` Inputs=`{0}` Outputs=`{1}`> 535 <NonExistentTask OutputResources=`aaa%253bbbb.resx; ccc%253bddd.resx`> 536 <Output ItemName=`Resource` TaskParameter=`OutputResources`/> 537 </NonExistentTask> 538 </Target> 539 540 <Target Name=`Build` DependsOnTargets=`GenerateResources`> 541 <Message Text=`Resources = @(Resource)`/> 542 </Target> 543 544 </Project> 545 546 ", inputFile, outputFile)); 547 548 logger.AssertLogContains("Resources = aaa%3bbbb.resx;ccc%3bddd.resx"); 549 } 550 finally 551 { 552 if (inputFile != null) File.Delete(inputFile); 553 if (outputFile != null) File.Delete(outputFile); 554 } 555 } 556 557 /// <summary> 558 /// Do an item transform, where the transform expression contains an unescaped semicolon as well 559 /// as an escaped percent sign. 560 /// </summary> 561 [Fact] ItemTransformContainingSemicolon()562 public void ItemTransformContainingSemicolon() 563 { 564 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(@" 565 566 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 567 <ItemGroup> 568 <TextFile Include=`X.txt`/> 569 <TextFile Include=`Y.txt`/> 570 <TextFile Include=`Z.txt`/> 571 </ItemGroup> 572 <Target Name=`Build`> 573 <Message Text=`Transformed item list: '@(TextFile->'%(FileName);%(FileName)%253b%(FileName)%(Extension)',' ')'` /> 574 </Target> 575 </Project> 576 577 "); 578 579 logger.AssertLogContains("Transformed item list: 'X;X%3bX.txt Y;Y%3bY.txt Z;Z%3bZ.txt'"); 580 } 581 582 #if FEATURE_TASKHOST 583 /// <summary> 584 /// Do an item transform, where the transform expression contains an unescaped semicolon as well 585 /// as an escaped percent sign. 586 /// </summary> 587 [Fact] 588 [Trait("Category", "mono-osx-failing")] ItemTransformContainingSemicolon_InTaskHost()589 public void ItemTransformContainingSemicolon_InTaskHost() 590 { 591 MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(@" 592 593 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 594 <UsingTask TaskName=`Message` AssemblyFile=`$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll` TaskFactory=`TaskHostFactory` /> 595 596 <ItemGroup> 597 <TextFile Include=`X.txt`/> 598 <TextFile Include=`Y.txt`/> 599 <TextFile Include=`Z.txt`/> 600 </ItemGroup> 601 <Target Name=`Build`> 602 <Message Text=`Transformed item list: '@(TextFile->'%(FileName);%(FileName)%253b%(FileName)%(Extension)',' ')'` /> 603 </Target> 604 </Project> 605 606 "); 607 608 logger.AssertLogContains("Transformed item list: 'X;X%3bX.txt Y;Y%3bY.txt Z;Z%3bZ.txt'"); 609 } 610 #endif 611 612 /// <summary> 613 /// Tests that when we add an item and are in a directory with characters in need of escaping, and the 614 /// item's FullPath metadata is retrieved, that a properly un-escaped version of the path is returned 615 /// </summary> 616 [Fact] FullPathMetadataOnItemUnescaped()617 public void FullPathMetadataOnItemUnescaped() 618 { 619 string projectName = "foo.proj"; 620 string projectRelativePath = "(jay's parens test)"; 621 string path = Path.Combine(Path.GetTempPath(), projectRelativePath); 622 string projectAbsolutePath = Path.Combine(path, projectName); 623 624 try 625 { 626 Directory.CreateDirectory(path); 627 628 ProjectRootElement projectElement = ProjectRootElement.Create(projectAbsolutePath); 629 ProjectItemGroupElement itemgroup = projectElement.AddItemGroup(); 630 itemgroup.AddItem("ProjectFile", projectName); 631 632 Project project = new Project(projectElement, null, null, new ProjectCollection()); 633 ProjectInstance projectInstance = project.CreateProjectInstance(); 634 635 IEnumerable<ProjectItemInstance> items = projectInstance.GetItems("ProjectFile"); 636 Assert.Equal(projectAbsolutePath, items.First().GetMetadataValue("FullPath")); 637 } 638 finally 639 { 640 if (File.Exists(projectAbsolutePath)) File.Delete(projectAbsolutePath); 641 if (Directory.Exists(path)) FileUtilities.DeleteWithoutTrailingBackslash(path); 642 } 643 } 644 645 646 /// <summary> 647 /// Test that we can pass in global properties containing escaped characters and they 648 /// won't be unescaped. 649 /// </summary> 650 [Fact] GlobalPropertyWithEscapedCharacters()651 public void GlobalPropertyWithEscapedCharacters() 652 { 653 MockLogger logger = new MockLogger(); 654 Project project = ObjectModelHelpers.CreateInMemoryProject(@" 655 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 656 <Target Name=`Build`> 657 <Message Text=`MyGlobalProperty = '$(MyGlobalProperty)'` /> 658 </Target> 659 </Project> 660 "); 661 662 project.SetGlobalProperty("MyGlobalProperty", "foo%253bbar"); 663 664 bool success = project.Build(logger); 665 Assert.True(success); // "Build failed. See Standard Out tab for details" 666 667 logger.AssertLogContains("MyGlobalProperty = 'foo%3bbar'"); 668 } 669 670 /// <summary> 671 /// If %2A (escaped '*') or %3F (escaped '?') is in an item's Include, it should be treated 672 /// literally, not as a wildcard 673 /// </summary> 674 [Fact] EscapedWildcardsShouldNotBeExpanded()675 public void EscapedWildcardsShouldNotBeExpanded() 676 { 677 MockLogger logger = new MockLogger(); 678 679 try 680 { 681 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 682 EscapingInProjectsHelper.CreateThreeWeirdoFiles(); 683 Project project = ObjectModelHelpers.CreateInMemoryProject(@" 684 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 685 <Target Name=`t`> 686 <ItemGroup> 687 <type Include=`%2A` Exclude=``/> 688 </ItemGroup> 689 <Message Text=`[@(type)]`/> 690 </Target> 691 </Project> 692 "); 693 694 bool success = project.Build(logger); 695 Assert.True(success); // "Build failed. See Standard Out tab for details" 696 logger.AssertLogContains("[*]"); 697 } 698 finally 699 { 700 ObjectModelHelpers.DeleteTempProjectDirectory(); 701 } 702 } 703 704 #if FEATURE_TASKHOST 705 /// <summary> 706 /// If %2A (escaped '*') or %3F (escaped '?') is in an item's Include, it should be treated 707 /// literally, not as a wildcard 708 /// </summary> 709 [Fact] 710 [Trait("Category", "mono-osx-failing")] EscapedWildcardsShouldNotBeExpanded_InTaskHost()711 public void EscapedWildcardsShouldNotBeExpanded_InTaskHost() 712 { 713 MockLogger logger = new MockLogger(); 714 715 try 716 { 717 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 718 EscapingInProjectsHelper.CreateThreeWeirdoFiles(); 719 Project project = ObjectModelHelpers.CreateInMemoryProject(@" 720 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 721 <UsingTask TaskName=`Message` AssemblyFile=`$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll` TaskFactory=`TaskHostFactory` /> 722 723 <Target Name=`t`> 724 <ItemGroup> 725 <type Include=`%2A` Exclude=``/> 726 </ItemGroup> 727 <Message Text=`[@(type)]`/> 728 </Target> 729 </Project> 730 "); 731 732 bool success = project.Build(logger); 733 Assert.True(success); // "Build failed. See Standard Out tab for details" 734 logger.AssertLogContains("[*]"); 735 } 736 finally 737 { 738 ObjectModelHelpers.DeleteTempProjectDirectory(); 739 } 740 } 741 #endif 742 743 /// <summary> 744 /// Parity with Orcas: Target names are always unescaped, and in fact, if there are two targets, 745 /// one the escaped version of the other, the second will override the first as though they had the 746 /// same name. 747 /// </summary> 748 [Fact] TargetNamesAlwaysUnescaped()749 public void TargetNamesAlwaysUnescaped() 750 { 751 bool exceptionCaught = false; 752 753 try 754 { 755 Project project = ObjectModelHelpers.CreateInMemoryProject(@" 756 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 757 <Target Name=`%24` /> 758 </Project> 759 "); 760 } 761 catch (InvalidProjectFileException ex) 762 { 763 string expectedErrorMessage = ResourceUtilities.FormatResourceString("NameInvalid", "$", "$"); 764 Assert.True(String.Equals(ex.Message, expectedErrorMessage, StringComparison.OrdinalIgnoreCase)); // "Wrong error message" 765 exceptionCaught = true; 766 } 767 768 Assert.True(exceptionCaught); // "Expected an InvalidProjectFileException" 769 } 770 771 /// <summary> 772 /// Parity with Orcas: Target names are always unescaped, and in fact, if there are two targets, 773 /// one the escaped version of the other, the second will override the first as though they had the 774 /// same name. 775 /// </summary> 776 [Fact] TargetNamesAlwaysUnescaped_Override()777 public void TargetNamesAlwaysUnescaped_Override() 778 { 779 Project project = ObjectModelHelpers.CreateInMemoryProject(@" 780 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 781 <Target Name=`%3B`> 782 <Message Text=`[WRONG]` /> 783 </Target> 784 <Target Name=`;`> 785 <Message Text=`[OVERRIDE]` /> 786 </Target> 787 </Project> 788 "); 789 MockLogger logger = new MockLogger(); 790 791 bool success = project.Build(logger); 792 Assert.True(success); // "Build failed. See Standard Out tab for details" 793 logger.AssertLogContains("[OVERRIDE]"); 794 } 795 796 /// <summary> 797 /// Tests that when we set metadata through the evaluation model, we do the right thing 798 /// </summary> 799 [Fact] SpecialCharactersInMetadataValueConstruction()800 public void SpecialCharactersInMetadataValueConstruction() 801 { 802 string projectString = @" 803 <Project DefaultTargets=""Build"" ToolsVersion=""msbuilddefaulttoolsversion"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> 804 <ItemGroup> 805 <None Include='MetadataTests'> 806 <EscapedSemicolon>%3B</EscapedSemicolon> 807 <EscapedDollarSign>%24</EscapedDollarSign> 808 </None> 809 </ItemGroup> 810 </Project>"; 811 #if FEATURE_XMLTEXTREADER 812 System.Xml.XmlReader reader = new System.Xml.XmlTextReader(new StringReader(projectString)); 813 #else 814 System.Xml.XmlReader reader = System.Xml.XmlReader.Create(new StringReader(projectString)); 815 #endif 816 Project project = new Project(reader); 817 ProjectItem item = project.GetItems("None").Single(); 818 819 EscapingInProjectsHelper.SpecialCharactersInMetadataValueTests(item); 820 } 821 822 /// <summary> 823 /// Tests that when we set metadata through the evaluation model, we do the right thing 824 /// </summary> 825 [Fact] SpecialCharactersInMetadataValueEvaluation()826 public void SpecialCharactersInMetadataValueEvaluation() 827 { 828 Project project = new Project(); 829 ProjectItem item = project.AddItem("None", "MetadataTests", new Dictionary<string, string> { 830 {"EscapedSemicolon", "%3B"}, //Microsoft.Build.Evaluation.ProjectCollection.Escape(";") 831 {"EscapedDollarSign", "%24"}, //Microsoft.Build.Evaluation.ProjectCollection.Escape("$") 832 }).Single(); 833 834 EscapingInProjectsHelper.SpecialCharactersInMetadataValueTests(item); 835 project.ReevaluateIfNecessary(); 836 EscapingInProjectsHelper.SpecialCharactersInMetadataValueTests(item); 837 } 838 839 /// <summary> 840 /// Say you have a scenario where a user is allowed to specify an arbitrary set of files (or 841 /// any sort of items) and expects to be able to get them back out as they were sent in. In addition, 842 /// the user can specify a macro (property) that can resolve to yet another arbitrary set of items. 843 /// We want to make sure that we do the right thing (assuming that the user escaped the information 844 /// correctly coming in) and don't mess up their set of items 845 /// </summary> 846 [Fact] CanGetCorrectListOfItemsWithSemicolonsInThem()847 public void CanGetCorrectListOfItemsWithSemicolonsInThem() 848 { 849 string projectString = @" 850 <Project DefaultTargets=""Build"" ToolsVersion=""msbuilddefaulttoolsversion"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> 851 <PropertyGroup> 852 <MyUserMacro>foo%3bbar</MyUserMacro> 853 </PropertyGroup> 854 <ItemGroup> 855 <CrazyList Include=""a"" /> 856 <CrazyList Include=""b%3bc"" /> 857 <CrazyList Include=""$(MyUserMacro)"" /> 858 </ItemGroup> 859 </Project>"; 860 861 #if FEATURE_XMLTEXTREADER 862 System.Xml.XmlReader reader = new System.Xml.XmlTextReader(new StringReader(projectString)); 863 #else 864 System.Xml.XmlReader reader = System.Xml.XmlReader.Create(new StringReader(projectString)); 865 #endif 866 Project project = new Project(reader); 867 IEnumerable<ProjectItem> items = project.GetItems("CrazyList"); 868 869 Assert.Equal(3, items.Count()); 870 Assert.Equal(items.ElementAt(0).EvaluatedInclude, "a"); 871 Assert.Equal(items.ElementAt(1).EvaluatedInclude, "b;c"); 872 Assert.Equal(items.ElementAt(2).EvaluatedInclude, "foo;bar"); 873 } 874 875 /// <summary> 876 /// Say you have a scenario where a user is allowed to specify an arbitrary set of files (or 877 /// any sort of items) and expects to be able to get them back out as they were sent in. In addition, 878 /// the user can specify a macro (property) that can resolve to yet another arbitrary set of items. 879 /// We want to make sure that we do the right thing (assuming that the user escaped the information 880 /// correctly coming in) and don't mess up their set of items 881 /// </summary> 882 [Fact] CanGetCorrectListOfItemsWithSemicolonsInThem2()883 public void CanGetCorrectListOfItemsWithSemicolonsInThem2() 884 { 885 string projectString = @" 886 <Project DefaultTargets=""Build"" ToolsVersion=""msbuilddefaulttoolsversion"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""> 887 <PropertyGroup> 888 <MyUserMacro>foo;bar</MyUserMacro> 889 </PropertyGroup> 890 <ItemGroup> 891 <CrazyList Include=""a"" /> 892 <CrazyList Include=""b%3bc"" /> 893 <CrazyList Include=""$(MyUserMacro)"" /> 894 </ItemGroup> 895 </Project>"; 896 897 #if FEATURE_XMLTEXTREADER 898 System.Xml.XmlReader reader = new System.Xml.XmlTextReader(new StringReader(projectString)); 899 #else 900 System.Xml.XmlReader reader = System.Xml.XmlReader.Create(new StringReader(projectString)); 901 #endif 902 Project project = new Project(reader); 903 IEnumerable<ProjectItem> items = project.GetItems("CrazyList"); 904 905 Assert.Equal(4, items.Count()); 906 Assert.Equal(items.ElementAt(0).EvaluatedInclude, "a"); 907 Assert.Equal(items.ElementAt(1).EvaluatedInclude, "b;c"); 908 Assert.Equal(items.ElementAt(2).EvaluatedInclude, "foo"); 909 Assert.Equal(items.ElementAt(3).EvaluatedInclude, "bar"); 910 } 911 } 912 913 #if FEATURE_COMPILE_IN_TESTS 914 public class FullProjectsUsingMicrosoftCommonTargets 915 { 916 private const string SolutionFileContentsWithUnusualCharacters = @"Microsoft Visual Studio Solution File, Format Version 11.00 917 Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `Cons.ole;!@(foo)'^(Application1`, `Console;!@(foo)'^(Application1\Cons.ole;!@(foo)'^(Application1.csproj`, `{770F2381-8C39-49E9-8C96-0538FA4349A7}` 918 EndProject 919 Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `Class;!@(foo)'^(Library1`, `Class;!@(foo)'^(Library1\Class;!@(foo)'^(Library1.csproj`, `{0B4B78CC-C752-43C2-BE9A-319D20216129}` 920 EndProject 921 Global 922 GlobalSection(SolutionConfigurationPlatforms) = preSolution 923 Debug|Any CPU = Debug|Any CPU 924 Release|Any CPU = Release|Any CPU 925 EndGlobalSection 926 GlobalSection(ProjectConfigurationPlatforms) = postSolution 927 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 928 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Debug|Any CPU.Build.0 = Debug|Any CPU 929 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Release|Any CPU.ActiveCfg = Release|Any CPU 930 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Release|Any CPU.Build.0 = Release|Any CPU 931 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 932 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Debug|Any CPU.Build.0 = Debug|Any CPU 933 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Release|Any CPU.ActiveCfg = Release|Any CPU 934 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Release|Any CPU.Build.0 = Release|Any CPU 935 EndGlobalSection 936 GlobalSection(SolutionProperties) = preSolution 937 HideSolutionNode = FALSE 938 EndGlobalSection 939 EndGlobal 940 "; 941 942 /// <summary> 943 /// ESCAPING: Escaping in conditionals is broken. 944 /// </summary> 945 [Fact] SemicolonInConfiguration()946 public void SemicolonInConfiguration() 947 { 948 ObjectModelHelpers.DeleteTempProjectDirectory(); 949 950 // --------------------- 951 // Foo.csproj 952 // --------------------- 953 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 954 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 955 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 956 <PropertyGroup> 957 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 958 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 959 <OutputType>Library</OutputType> 960 <AssemblyName>ClassLibrary16</AssemblyName> 961 </PropertyGroup> 962 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'a%3bb%27c|AnyCPU' `> 963 <OutputPath>bin\a%3bb%27c\</OutputPath> 964 </PropertyGroup> 965 <ItemGroup> 966 <Reference Include=`System` /> 967 <Compile Include=`Class1.cs` /> 968 </ItemGroup> 969 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 970 </Project> 971 "); 972 973 // --------------------- 974 // Class1.cs 975 // --------------------- 976 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 977 namespace ClassLibrary16 978 { 979 public class Class1 980 { 981 } 982 } 983 "); 984 985 // Create a logger. 986 MockLogger logger = new MockLogger(); 987 988 Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory("foo.csproj"); 989 990 // Build the default targets using the Configuration "a;b'c". 991 project.SetGlobalProperty("Configuration", EscapingUtilities.Escape("a;b'c")); 992 bool success = project.Build(logger); 993 Assert.True(success); // "Build failed. See Standard Out tab for details" 994 995 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\a;b'c\ClassLibrary16.dll"); 996 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\a;b'c\ClassLibrary16.dll"); 997 998 logger.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\a;b'c\ClassLibrary16.dll"))); 999 } 1000 1001 #if FEATURE_TASKHOST 1002 /// <summary> 1003 /// ESCAPING: Escaping in conditionals is broken. 1004 /// </summary> 1005 [Fact] SemicolonInConfiguration_UsingTaskHost()1006 public void SemicolonInConfiguration_UsingTaskHost() 1007 { 1008 string originalOverrideTaskHostVariable = Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC"); 1009 1010 try 1011 { 1012 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); 1013 ObjectModelHelpers.DeleteTempProjectDirectory(); 1014 1015 // --------------------- 1016 // Foo.csproj 1017 // --------------------- 1018 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1019 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1020 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1021 <PropertyGroup> 1022 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1023 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1024 <OutputType>Library</OutputType> 1025 <AssemblyName>ClassLibrary16</AssemblyName> 1026 </PropertyGroup> 1027 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'a%3bb%27c|AnyCPU' `> 1028 <OutputPath>bin\a%3bb%27c\</OutputPath> 1029 </PropertyGroup> 1030 <ItemGroup> 1031 <Reference Include=`System` /> 1032 <Compile Include=`Class1.cs` /> 1033 </ItemGroup> 1034 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1035 </Project> 1036 "); 1037 1038 // --------------------- 1039 // Class1.cs 1040 // --------------------- 1041 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 1042 namespace ClassLibrary16 1043 { 1044 public class Class1 1045 { 1046 } 1047 } 1048 "); 1049 1050 // Create a logger. 1051 MockLogger logger = new MockLogger(); 1052 1053 Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory("foo.csproj"); 1054 1055 // Build the default targets using the Configuration "a;b'c". 1056 project.SetGlobalProperty("Configuration", EscapingUtilities.Escape("a;b'c")); 1057 bool success = project.Build(logger); 1058 Assert.True(success); // "Build failed. See Standard Out tab for details" 1059 1060 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\a;b'c\ClassLibrary16.dll"); 1061 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\a;b'c\ClassLibrary16.dll"); 1062 1063 logger.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\a;b'c\ClassLibrary16.dll"))); 1064 } 1065 finally 1066 { 1067 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", originalOverrideTaskHostVariable); 1068 } 1069 } 1070 #endif 1071 1072 /// <summary> 1073 /// ESCAPING: CopyBuildTarget target fails if the output assembly name contains a semicolon or single-quote 1074 /// </summary> 1075 [Fact] SemicolonInAssemblyName()1076 public void SemicolonInAssemblyName() 1077 { 1078 ObjectModelHelpers.DeleteTempProjectDirectory(); 1079 1080 // --------------------- 1081 // Foo.csproj 1082 // --------------------- 1083 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1084 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1085 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1086 <PropertyGroup> 1087 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1088 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1089 <OutputType>Library</OutputType> 1090 <AssemblyName>Class%3bLibrary16</AssemblyName> 1091 </PropertyGroup> 1092 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1093 <OutputPath>bin\Debug\</OutputPath> 1094 </PropertyGroup> 1095 <ItemGroup> 1096 <Reference Include=`System` /> 1097 <Compile Include=`Class1.cs` /> 1098 </ItemGroup> 1099 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1100 </Project> 1101 "); 1102 1103 // --------------------- 1104 // Class1.cs 1105 // --------------------- 1106 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 1107 namespace ClassLibrary16 1108 { 1109 public class Class1 1110 { 1111 } 1112 } 1113 "); 1114 1115 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 1116 1117 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class;Library16.dll", @"Did not find expected file obj\debug\Class;Library16.dll"); 1118 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class;Library16.pdb", @"Did not find expected file obj\debug\Class;Library16.pdb"); 1119 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\Class;Library16.dll", @"Did not find expected file bin\debug\Class;Library16.dll"); 1120 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class;Library16.pdb", @"Did not find expected file obj\debug\Class;Library16.pdb"); 1121 1122 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\Class;Library16.dll"))); 1123 } 1124 1125 #if FEATURE_TASKHOST 1126 /// <summary> 1127 /// ESCAPING: CopyBuildTarget target fails if the output assembly name contains a semicolon or single-quote 1128 /// </summary> 1129 [Fact] SemicolonInAssemblyName_UsingTaskHost()1130 public void SemicolonInAssemblyName_UsingTaskHost() 1131 { 1132 string originalOverrideTaskHostVariable = Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC"); 1133 1134 try 1135 { 1136 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); 1137 ObjectModelHelpers.DeleteTempProjectDirectory(); 1138 1139 // --------------------- 1140 // Foo.csproj 1141 // --------------------- 1142 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1143 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1144 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1145 <PropertyGroup> 1146 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1147 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1148 <OutputType>Library</OutputType> 1149 <AssemblyName>Class%3bLibrary16</AssemblyName> 1150 </PropertyGroup> 1151 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1152 <OutputPath>bin\Debug\</OutputPath> 1153 </PropertyGroup> 1154 <ItemGroup> 1155 <Reference Include=`System` /> 1156 <Compile Include=`Class1.cs` /> 1157 </ItemGroup> 1158 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1159 </Project> 1160 "); 1161 1162 // --------------------- 1163 // Class1.cs 1164 // --------------------- 1165 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 1166 namespace ClassLibrary16 1167 { 1168 public class Class1 1169 { 1170 } 1171 } 1172 "); 1173 1174 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 1175 1176 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class;Library16.dll", @"Did not find expected file obj\debug\Class;Library16.dll"); 1177 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class;Library16.pdb", @"Did not find expected file obj\debug\Class;Library16.pdb"); 1178 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\Class;Library16.dll", @"Did not find expected file bin\debug\Class;Library16.dll"); 1179 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class;Library16.pdb", @"Did not find expected file obj\debug\Class;Library16.pdb"); 1180 1181 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\Class;Library16.dll"))); 1182 } 1183 finally 1184 { 1185 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", originalOverrideTaskHostVariable); 1186 } 1187 } 1188 #endif 1189 1190 /// <summary> 1191 /// ESCAPING: Conversion Issue: Properties with $(xxx) as literals are not being converted correctly 1192 /// </summary> 1193 [Fact] DollarSignInAssemblyName()1194 public void DollarSignInAssemblyName() 1195 { 1196 ObjectModelHelpers.DeleteTempProjectDirectory(); 1197 1198 // --------------------- 1199 // Foo.csproj 1200 // --------------------- 1201 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1202 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1203 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1204 <PropertyGroup> 1205 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1206 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1207 <OutputType>Library</OutputType> 1208 <AssemblyName>Class%24%28prop%29Library16</AssemblyName> 1209 </PropertyGroup> 1210 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1211 <OutputPath>bin\Debug\</OutputPath> 1212 </PropertyGroup> 1213 <ItemGroup> 1214 <Reference Include=`System` /> 1215 <Compile Include=`Class1.cs` /> 1216 </ItemGroup> 1217 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1218 </Project> 1219 "); 1220 1221 // --------------------- 1222 // Class1.cs 1223 // --------------------- 1224 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 1225 namespace ClassLibrary16 1226 { 1227 public class Class1 1228 { 1229 } 1230 } 1231 "); 1232 1233 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 1234 1235 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class$(prop)Library16.dll", @"Did not find expected file obj\debug\Class$(prop)Library16.dll"); 1236 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class$(prop)Library16.pdb", @"Did not find expected file obj\debug\Class$(prop)Library16.pdb"); 1237 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\Class$(prop)Library16.dll", @"Did not find expected file bin\debug\Class$(prop)Library16.dll"); 1238 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\Class$(prop)Library16.pdb", @"Did not find expected file bin\debug\Class$(prop)Library16.pdb"); 1239 1240 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\Class$(prop)Library16.dll"))); 1241 } 1242 1243 #if FEATURE_TASKHOST 1244 /// <summary> 1245 /// ESCAPING: Conversion Issue: Properties with $(xxx) as literals are not being converted correctly 1246 /// </summary> 1247 [Fact] DollarSignInAssemblyName_UsingTaskHost()1248 public void DollarSignInAssemblyName_UsingTaskHost() 1249 { 1250 string originalOverrideTaskHostVariable = Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC"); 1251 1252 try 1253 { 1254 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); 1255 ObjectModelHelpers.DeleteTempProjectDirectory(); 1256 1257 // --------------------- 1258 // Foo.csproj 1259 // --------------------- 1260 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1261 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1262 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1263 <PropertyGroup> 1264 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1265 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1266 <OutputType>Library</OutputType> 1267 <AssemblyName>Class%24%28prop%29Library16</AssemblyName> 1268 </PropertyGroup> 1269 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1270 <OutputPath>bin\Debug\</OutputPath> 1271 </PropertyGroup> 1272 <ItemGroup> 1273 <Reference Include=`System` /> 1274 <Compile Include=`Class1.cs` /> 1275 </ItemGroup> 1276 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1277 </Project> 1278 "); 1279 1280 // --------------------- 1281 // Class1.cs 1282 // --------------------- 1283 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 1284 namespace ClassLibrary16 1285 { 1286 public class Class1 1287 { 1288 } 1289 } 1290 "); 1291 1292 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 1293 1294 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class$(prop)Library16.dll", @"Did not find expected file obj\debug\Class$(prop)Library16.dll"); 1295 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\Class$(prop)Library16.pdb", @"Did not find expected file obj\debug\Class$(prop)Library16.pdb"); 1296 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\Class$(prop)Library16.dll", @"Did not find expected file bin\debug\Class$(prop)Library16.dll"); 1297 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\Class$(prop)Library16.pdb", @"Did not find expected file bin\debug\Class$(prop)Library16.pdb"); 1298 1299 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\Class$(prop)Library16.dll"))); 1300 } 1301 finally 1302 { 1303 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", originalOverrideTaskHostVariable); 1304 } 1305 } 1306 #endif 1307 1308 /// <summary> 1309 /// This is the case when one of the source code files in the project has a filename containing a semicolon. 1310 /// </summary> 1311 [Fact] SemicolonInSourceCodeFilename()1312 public void SemicolonInSourceCodeFilename() 1313 { 1314 ObjectModelHelpers.DeleteTempProjectDirectory(); 1315 1316 // --------------------- 1317 // Foo.csproj 1318 // --------------------- 1319 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1320 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1321 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1322 <PropertyGroup> 1323 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1324 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1325 <OutputType>Library</OutputType> 1326 <AssemblyName>ClassLibrary16</AssemblyName> 1327 </PropertyGroup> 1328 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1329 <OutputPath>bin\Debug\</OutputPath> 1330 </PropertyGroup> 1331 <ItemGroup> 1332 <Reference Include=`System` /> 1333 <Compile Include=`Class%3b1.cs` /> 1334 </ItemGroup> 1335 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1336 </Project> 1337 "); 1338 1339 // --------------------- 1340 // Class1.cs 1341 // --------------------- 1342 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class;1.cs", @" 1343 namespace ClassLibrary16 1344 { 1345 public class Class1 1346 { 1347 } 1348 } 1349 "); 1350 1351 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 1352 1353 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\ClassLibrary16.dll", @"Did not find expected file obj\debug\ClassLibrary16.dll"); 1354 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\ClassLibrary16.pdb", @"Did not find expected file obj\debug\ClassLibrary16.pdb"); 1355 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\ClassLibrary16.dll", @"Did not find expected file bin\debug\ClassLibrary16.dll"); 1356 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\ClassLibrary16.pdb", @"Did not find expected file bin\debug\ClassLibrary16.pdb"); 1357 1358 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\ClassLibrary16.dll"))); 1359 } 1360 1361 #if FEATURE_TASKHOST 1362 /// <summary> 1363 /// This is the case when one of the source code files in the project has a filename containing a semicolon. 1364 /// </summary> 1365 [Fact] SemicolonInSourceCodeFilename_UsingTaskHost()1366 public void SemicolonInSourceCodeFilename_UsingTaskHost() 1367 { 1368 string originalOverrideTaskHostVariable = Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC"); 1369 1370 try 1371 { 1372 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); 1373 ObjectModelHelpers.DeleteTempProjectDirectory(); 1374 1375 // --------------------- 1376 // Foo.csproj 1377 // --------------------- 1378 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 1379 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1380 <Import Project=`$(MSBuildBinPath)\Microsoft.Common.props` /> 1381 <PropertyGroup> 1382 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1383 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1384 <OutputType>Library</OutputType> 1385 <AssemblyName>ClassLibrary16</AssemblyName> 1386 </PropertyGroup> 1387 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1388 <OutputPath>bin\Debug\</OutputPath> 1389 </PropertyGroup> 1390 <ItemGroup> 1391 <Reference Include=`System` /> 1392 <Compile Include=`Class%3b1.cs` /> 1393 </ItemGroup> 1394 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1395 </Project> 1396 "); 1397 1398 // --------------------- 1399 // Class1.cs 1400 // --------------------- 1401 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class;1.cs", @" 1402 namespace ClassLibrary16 1403 { 1404 public class Class1 1405 { 1406 } 1407 } 1408 "); 1409 1410 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 1411 1412 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\ClassLibrary16.dll", @"Did not find expected file obj\debug\ClassLibrary16.dll"); 1413 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\debug\ClassLibrary16.pdb", @"Did not find expected file obj\debug\ClassLibrary16.pdb"); 1414 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\ClassLibrary16.dll", @"Did not find expected file bin\debug\ClassLibrary16.dll"); 1415 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\debug\ClassLibrary16.pdb", @"Did not find expected file bin\debug\ClassLibrary16.pdb"); 1416 1417 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\ClassLibrary16.dll"))); 1418 } 1419 finally 1420 { 1421 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", originalOverrideTaskHostVariable); 1422 } 1423 } 1424 #endif 1425 1426 /// <summary> 1427 /// Build a .SLN file using MSBuild. The .SLN and the projects contained within 1428 /// have all sorts of crazy characters in their name. There 1429 /// is even a P2P reference between the two projects in the .SLN. 1430 /// </summary> 1431 [Fact(Skip = "This is a known issue in Roslyn. This test should be enabled if Roslyn is updated for this scenario.")] SolutionWithLotsaCrazyCharacters()1432 public void SolutionWithLotsaCrazyCharacters() 1433 { 1434 ObjectModelHelpers.DeleteTempProjectDirectory(); 1435 1436 // --------------------------------------------------------------------- 1437 // Console;!@(foo)'^(Application1.sln 1438 // --------------------------------------------------------------------- 1439 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1440 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1.sln", 1441 SolutionFileContentsWithUnusualCharacters); 1442 1443 // --------------------------------------------------------------------- 1444 // Console;!@(foo)'^(Application1.csproj 1445 // --------------------------------------------------------------------- 1446 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1447 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\Cons.ole;!@(foo)'^(Application1.csproj", 1448 1449 @" 1450 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1451 <PropertyGroup> 1452 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1453 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1454 <ProductVersion>8.0.50510</ProductVersion> 1455 <SchemaVersion>2.0</SchemaVersion> 1456 <ProjectGuid>{770F2381-8C39-49E9-8C96-0538FA4349A7}</ProjectGuid> 1457 <OutputType>Exe</OutputType> 1458 <AppDesignerFolder>Properties</AppDesignerFolder> 1459 <RootNamespace>Console____foo____Application1</RootNamespace> 1460 <AssemblyName>Console%3b!%40%28foo%29%27^%28Application1</AssemblyName> 1461 </PropertyGroup> 1462 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1463 <DebugSymbols>true</DebugSymbols> 1464 <DebugType>full</DebugType> 1465 <Optimize>false</Optimize> 1466 <OutputPath>bin\Debug\</OutputPath> 1467 <DefineConstants>DEBUG;TRACE</DefineConstants> 1468 <ErrorReport>prompt</ErrorReport> 1469 <WarningLevel>4</WarningLevel> 1470 </PropertyGroup> 1471 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Release|AnyCPU' `> 1472 <DebugType>pdbonly</DebugType> 1473 <Optimize>true</Optimize> 1474 <OutputPath>bin\Release\</OutputPath> 1475 <DefineConstants>TRACE</DefineConstants> 1476 <ErrorReport>prompt</ErrorReport> 1477 <WarningLevel>4</WarningLevel> 1478 </PropertyGroup> 1479 <ItemGroup> 1480 <Reference Include=`System` /> 1481 <Reference Include=`System.Data` /> 1482 <Reference Include=`System.Xml` /> 1483 </ItemGroup> 1484 <ItemGroup> 1485 <Compile Include=`Program.cs` /> 1486 </ItemGroup> 1487 <ItemGroup> 1488 <ProjectReference Include=`..\Class%3b!%40%28foo%29%27^%28Library1\Class%3b!%40%28foo%29%27^%28Library1.csproj`> 1489 <Project>{0B4B78CC-C752-43C2-BE9A-319D20216129}</Project> 1490 <Name>Class%3b!%40%28foo%29%27^%28Library1</Name> 1491 </ProjectReference> 1492 </ItemGroup> 1493 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1494 </Project> 1495 "); 1496 1497 // --------------------------------------------------------------------- 1498 // Program.cs 1499 // --------------------------------------------------------------------- 1500 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1501 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\Program.cs", 1502 1503 @" 1504 using System; 1505 using System.Collections.Generic; 1506 using System.Text; 1507 1508 namespace Console____foo____Application1 1509 { 1510 class Program 1511 { 1512 static void Main(string[] args) 1513 { 1514 Class____foo____Library1.Class1 foo = new Class____foo____Library1.Class1(); 1515 } 1516 } 1517 } 1518 "); 1519 1520 // --------------------------------------------------------------------- 1521 // Class;!@(foo)'^(Library1.csproj 1522 // --------------------------------------------------------------------- 1523 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1524 @"SLN;!@(foo)'^1\Class;!@(foo)'^(Library1\Class;!@(foo)'^(Library1.csproj", 1525 1526 @" 1527 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1528 <PropertyGroup> 1529 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1530 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1531 <ProductVersion>8.0.50510</ProductVersion> 1532 <SchemaVersion>2.0</SchemaVersion> 1533 <ProjectGuid>{0B4B78CC-C752-43C2-BE9A-319D20216129}</ProjectGuid> 1534 <OutputType>Library</OutputType> 1535 <AppDesignerFolder>Properties</AppDesignerFolder> 1536 <RootNamespace>Class____foo____Library1</RootNamespace> 1537 <AssemblyName>Class%3b!%40%28foo%29%27^%28Library1</AssemblyName> 1538 </PropertyGroup> 1539 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1540 <DebugSymbols>true</DebugSymbols> 1541 <DebugType>full</DebugType> 1542 <Optimize>false</Optimize> 1543 <OutputPath>bin\Debug\</OutputPath> 1544 <DefineConstants>DEBUG;TRACE</DefineConstants> 1545 <ErrorReport>prompt</ErrorReport> 1546 <WarningLevel>4</WarningLevel> 1547 </PropertyGroup> 1548 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Release|AnyCPU' `> 1549 <DebugType>pdbonly</DebugType> 1550 <Optimize>true</Optimize> 1551 <OutputPath>bin\Release\</OutputPath> 1552 <DefineConstants>TRACE</DefineConstants> 1553 <ErrorReport>prompt</ErrorReport> 1554 <WarningLevel>4</WarningLevel> 1555 </PropertyGroup> 1556 <ItemGroup> 1557 <Reference Include=`System` /> 1558 <Reference Include=`System.Data` /> 1559 <Reference Include=`System.Xml` /> 1560 </ItemGroup> 1561 <ItemGroup> 1562 <Compile Include=`Class1.cs` /> 1563 </ItemGroup> 1564 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1565 </Project> 1566 "); 1567 1568 // --------------------------------------------------------------------- 1569 // Class1.cs 1570 // --------------------------------------------------------------------- 1571 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1572 @"SLN;!@(foo)'^1\Class;!@(foo)'^(Library1\Class1.cs", 1573 1574 @" 1575 namespace Class____foo____Library1 1576 { 1577 public class Class1 1578 { 1579 } 1580 } 1581 "); 1582 1583 // Cons.ole;!@(foo)'^(Application1 1584 string targetForFirstProject = "Cons_ole_!__foo__^_Application1"; 1585 1586 MockLogger log = ObjectModelHelpers.BuildTempProjectFileWithTargetsExpectSuccess(@"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1.sln", new string[] { targetForFirstProject }, null); 1587 1588 Assert.True(File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\bin\debug\Console;!@(foo)'^(Application1.exe"))); // @"Did not find expected file Console;!@(foo)'^(Application1.exe" 1589 } 1590 1591 #if FEATURE_TASKHOST 1592 /// <summary> 1593 /// Build a .SLN file using MSBuild. The .SLN and the projects contained within 1594 /// have all sorts of crazy characters in their name. There 1595 /// is even a P2P reference between the two projects in the .SLN. 1596 /// </summary> 1597 [Fact(Skip = "This is a known issue in Roslyn. This test should be enabled if Roslyn is updated for this scenario.")] SolutionWithLotsaCrazyCharacters_UsingTaskHost()1598 public void SolutionWithLotsaCrazyCharacters_UsingTaskHost() 1599 { 1600 string originalOverrideTaskHostVariable = Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC"); 1601 1602 try 1603 { 1604 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); 1605 ObjectModelHelpers.DeleteTempProjectDirectory(); 1606 1607 // --------------------------------------------------------------------- 1608 // Console;!@(foo)'^(Application1.sln 1609 // --------------------------------------------------------------------- 1610 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1611 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1.sln", 1612 SolutionFileContentsWithUnusualCharacters); 1613 1614 // --------------------------------------------------------------------- 1615 // Console;!@(foo)'^(Application1.csproj 1616 // --------------------------------------------------------------------- 1617 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1618 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\Cons.ole;!@(foo)'^(Application1.csproj", 1619 1620 @" 1621 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1622 <PropertyGroup> 1623 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1624 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1625 <ProductVersion>8.0.50510</ProductVersion> 1626 <SchemaVersion>2.0</SchemaVersion> 1627 <ProjectGuid>{770F2381-8C39-49E9-8C96-0538FA4349A7}</ProjectGuid> 1628 <OutputType>Exe</OutputType> 1629 <AppDesignerFolder>Properties</AppDesignerFolder> 1630 <RootNamespace>Console____foo____Application1</RootNamespace> 1631 <AssemblyName>Console%3b!%40%28foo%29%27^%28Application1</AssemblyName> 1632 </PropertyGroup> 1633 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1634 <DebugSymbols>true</DebugSymbols> 1635 <DebugType>full</DebugType> 1636 <Optimize>false</Optimize> 1637 <OutputPath>bin\Debug\</OutputPath> 1638 <DefineConstants>DEBUG;TRACE</DefineConstants> 1639 <ErrorReport>prompt</ErrorReport> 1640 <WarningLevel>4</WarningLevel> 1641 </PropertyGroup> 1642 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Release|AnyCPU' `> 1643 <DebugType>pdbonly</DebugType> 1644 <Optimize>true</Optimize> 1645 <OutputPath>bin\Release\</OutputPath> 1646 <DefineConstants>TRACE</DefineConstants> 1647 <ErrorReport>prompt</ErrorReport> 1648 <WarningLevel>4</WarningLevel> 1649 </PropertyGroup> 1650 <ItemGroup> 1651 <Reference Include=`System` /> 1652 <Reference Include=`System.Data` /> 1653 <Reference Include=`System.Xml` /> 1654 </ItemGroup> 1655 <ItemGroup> 1656 <Compile Include=`Program.cs` /> 1657 </ItemGroup> 1658 <ItemGroup> 1659 <ProjectReference Include=`..\Class%3b!%40%28foo%29%27^%28Library1\Class%3b!%40%28foo%29%27^%28Library1.csproj`> 1660 <Project>{0B4B78CC-C752-43C2-BE9A-319D20216129}</Project> 1661 <Name>Class%3b!%40%28foo%29%27^%28Library1</Name> 1662 </ProjectReference> 1663 </ItemGroup> 1664 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1665 </Project> 1666 "); 1667 1668 // --------------------------------------------------------------------- 1669 // Program.cs 1670 // --------------------------------------------------------------------- 1671 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1672 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\Program.cs", 1673 1674 @" 1675 using System; 1676 using System.Collections.Generic; 1677 using System.Text; 1678 1679 namespace Console____foo____Application1 1680 { 1681 class Program 1682 { 1683 static void Main(string[] args) 1684 { 1685 Class____foo____Library1.Class1 foo = new Class____foo____Library1.Class1(); 1686 } 1687 } 1688 } 1689 "); 1690 1691 // --------------------------------------------------------------------- 1692 // Class;!@(foo)'^(Library1.csproj 1693 // --------------------------------------------------------------------- 1694 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1695 @"SLN;!@(foo)'^1\Class;!@(foo)'^(Library1\Class;!@(foo)'^(Library1.csproj", 1696 1697 @" 1698 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`http://schemas.microsoft.com/developer/msbuild/2003`> 1699 <PropertyGroup> 1700 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 1701 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 1702 <ProductVersion>8.0.50510</ProductVersion> 1703 <SchemaVersion>2.0</SchemaVersion> 1704 <ProjectGuid>{0B4B78CC-C752-43C2-BE9A-319D20216129}</ProjectGuid> 1705 <OutputType>Library</OutputType> 1706 <AppDesignerFolder>Properties</AppDesignerFolder> 1707 <RootNamespace>Class____foo____Library1</RootNamespace> 1708 <AssemblyName>Class%3b!%40%28foo%29%27^%28Library1</AssemblyName> 1709 </PropertyGroup> 1710 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 1711 <DebugSymbols>true</DebugSymbols> 1712 <DebugType>full</DebugType> 1713 <Optimize>false</Optimize> 1714 <OutputPath>bin\Debug\</OutputPath> 1715 <DefineConstants>DEBUG;TRACE</DefineConstants> 1716 <ErrorReport>prompt</ErrorReport> 1717 <WarningLevel>4</WarningLevel> 1718 </PropertyGroup> 1719 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Release|AnyCPU' `> 1720 <DebugType>pdbonly</DebugType> 1721 <Optimize>true</Optimize> 1722 <OutputPath>bin\Release\</OutputPath> 1723 <DefineConstants>TRACE</DefineConstants> 1724 <ErrorReport>prompt</ErrorReport> 1725 <WarningLevel>4</WarningLevel> 1726 </PropertyGroup> 1727 <ItemGroup> 1728 <Reference Include=`System` /> 1729 <Reference Include=`System.Data` /> 1730 <Reference Include=`System.Xml` /> 1731 </ItemGroup> 1732 <ItemGroup> 1733 <Compile Include=`Class1.cs` /> 1734 </ItemGroup> 1735 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 1736 </Project> 1737 "); 1738 1739 // --------------------------------------------------------------------- 1740 // Class1.cs 1741 // --------------------------------------------------------------------- 1742 ObjectModelHelpers.CreateFileInTempProjectDirectory( 1743 @"SLN;!@(foo)'^1\Class;!@(foo)'^(Library1\Class1.cs", 1744 1745 @" 1746 namespace Class____foo____Library1 1747 { 1748 public class Class1 1749 { 1750 } 1751 } 1752 "); 1753 1754 // Cons.ole;!@(foo)'^(Application1 1755 string targetForFirstProject = "Cons_ole_!__foo__^_Application1"; 1756 1757 MockLogger log = ObjectModelHelpers.BuildTempProjectFileWithTargetsExpectSuccess(@"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1.sln", new string[] { targetForFirstProject }, null); 1758 1759 Assert.True(File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\bin\debug\Console;!@(foo)'^(Application1.exe"))); // @"Did not find expected file Console;!@(foo)'^(Application1.exe" 1760 } 1761 finally 1762 { 1763 Environment.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", originalOverrideTaskHostVariable); 1764 } 1765 } 1766 #endif 1767 } 1768 #endif 1769 1770 internal class EscapingInProjectsHelper 1771 { 1772 /// <summary> 1773 /// Deletes all *.weirdo files from the temp path, and dumps 3 files there -- 1774 /// a.weirdo, b.weirdo, c.weirdo. This is so that we can exercise our wildcard 1775 /// matching a little bit without having to plumb mock objects all the way through 1776 /// the engine. 1777 /// </summary> CreateThreeWeirdoFiles()1778 internal static void CreateThreeWeirdoFiles() 1779 { 1780 ObjectModelHelpers.DeleteTempProjectDirectory(); 1781 1782 // Create 3 files in the temp path -- a.weirdo, b.weirdo, and c.weirdo. 1783 File.WriteAllText(Path.Combine(ObjectModelHelpers.TempProjectDir, "a.weirdo"), String.Empty); 1784 File.WriteAllText(Path.Combine(ObjectModelHelpers.TempProjectDir, "b.weirdo"), String.Empty); 1785 File.WriteAllText(Path.Combine(ObjectModelHelpers.TempProjectDir, "c.weirdo"), String.Empty); 1786 } 1787 1788 /// <summary> 1789 /// Given a project and an item type, gets the items of that type, and renames an item 1790 /// with the old evaluated include to have the new evaluated include instead. 1791 /// </summary> 1792 /// <param name="project"></param> 1793 /// <param name="itemType"></param> 1794 /// <param name="oldEvaluatedInclude"></param> 1795 /// <param name="newEvaluatedInclude"></param> ModifyItemOfTypeInProject(Project project, string itemType, string oldEvaluatedInclude, string newEvaluatedInclude)1796 internal static IEnumerable<ProjectItem> ModifyItemOfTypeInProject(Project project, string itemType, string oldEvaluatedInclude, string newEvaluatedInclude) 1797 { 1798 IEnumerable<ProjectItem> itemsToMatch = project.GetItems(itemType); 1799 List<ProjectItem> matchingItems = new List<ProjectItem>(); 1800 1801 foreach (ProjectItem item in itemsToMatch) 1802 { 1803 if (String.Equals(item.EvaluatedInclude, oldEvaluatedInclude, StringComparison.OrdinalIgnoreCase)) 1804 { 1805 matchingItems.Add(item); 1806 } 1807 } 1808 1809 for (int i = 0; i < matchingItems.Count; i++) 1810 { 1811 matchingItems[i].Rename(newEvaluatedInclude); 1812 } 1813 1814 return matchingItems; 1815 } 1816 1817 /// <summary> 1818 /// Helper for SpecialCharactersInMetadataValue tests 1819 /// </summary> SpecialCharactersInMetadataValueTests(ProjectItem item)1820 internal static void SpecialCharactersInMetadataValueTests(ProjectItem item) 1821 { 1822 Assert.Equal("%3B", item.GetMetadata("EscapedSemicolon").UnevaluatedValue); 1823 Assert.Equal("%3B", item.GetMetadata("EscapedSemicolon").EvaluatedValueEscaped); 1824 Assert.Equal(";", item.GetMetadata("EscapedSemicolon").EvaluatedValue); 1825 Assert.Equal("%3B", Project.GetMetadataValueEscaped(item, "EscapedSemicolon")); 1826 Assert.Equal(";", item.GetMetadataValue("EscapedSemicolon")); 1827 1828 Assert.Equal("%24", item.GetMetadata("EscapedDollarSign").UnevaluatedValue); 1829 Assert.Equal("%24", item.GetMetadata("EscapedDollarSign").EvaluatedValueEscaped); 1830 Assert.Equal("$", item.GetMetadata("EscapedDollarSign").EvaluatedValue); 1831 Assert.Equal("%24", Project.GetMetadataValueEscaped(item, "EscapedDollarSign")); 1832 Assert.Equal("$", item.GetMetadataValue("EscapedDollarSign")); 1833 } 1834 } 1835 } 1836