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.IO; 6 using System.Collections.Generic; 7 using System.Text; 8 using System.Reflection; 9 10 using NUnit.Framework; 11 12 using Microsoft.Build.UnitTests; 13 14 using Microsoft.Build.Utilities; 15 using Microsoft.Build.Framework; 16 using Microsoft.Build.BuildEngine; 17 using Microsoft.Build.UnitTests.Project_Tests; 18 19 namespace Microsoft.Build.UnitTests.EscapingInProjects_Tests 20 { 21 /// <summary> 22 /// Test task that just logs the parameters it receives. 23 /// </summary> 24 /// <owner>RGoel</owner> 25 public class MyTestTask : Task 26 { 27 private ITaskItem taskItemParam; 28 public ITaskItem TaskItemParam 29 { 30 get 31 { 32 return taskItemParam; 33 } 34 35 set 36 { 37 taskItemParam = value; 38 } 39 } 40 Execute()41 override public bool Execute() 42 { 43 if (TaskItemParam != null) 44 { 45 Log.LogMessageFromText("Received TaskItemParam: " + TaskItemParam.ItemSpec, MessageImportance.High); 46 } 47 48 return true; 49 } 50 } 51 52 [TestFixture] 53 public class SimpleScenarios 54 { 55 /// <summary> 56 /// Make sure I can define a property with escaped characters and pass it into 57 /// a string parameter of a task, in this case the Message task. 58 /// </summary> 59 /// <owner>RGoel</owner> 60 [Test] SemicolonInPropertyPassedIntoStringParam()61 public void SemicolonInPropertyPassedIntoStringParam() 62 { 63 MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(@" 64 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 65 <PropertyGroup> 66 <MyPropertyWithSemicolons>abc %3b def %3b ghi</MyPropertyWithSemicolons> 67 </PropertyGroup> 68 <Target Name=`Build`> 69 <Message Text=`Property value is '$(MyPropertyWithSemicolons)'` /> 70 </Target> 71 </Project> 72 "); 73 74 logger.AssertLogContains("Property value is 'abc ; def ; ghi'"); 75 } 76 77 /// <summary> 78 /// Make sure I can define a property with escaped characters and pass it into 79 /// an ITaskItem[] task parameter. 80 /// </summary> 81 [Test] SemicolonInPropertyPassedIntoITaskItemParam()82 public void SemicolonInPropertyPassedIntoITaskItemParam() 83 { 84 MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(String.Format(@" 85 86 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 87 88 <UsingTask TaskName=`Microsoft.Build.UnitTests.EscapingInProjects_Tests.MyTestTask` AssemblyFile=`{0}` /> 89 90 <PropertyGroup> 91 <MyPropertyWithSemicolons>abc %3b def %3b ghi</MyPropertyWithSemicolons> 92 </PropertyGroup> 93 94 <Target Name=`Build`> 95 <MyTestTask TaskItemParam=`123 $(MyPropertyWithSemicolons) 789` /> 96 </Target> 97 98 </Project> 99 100 ", new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath)); 101 102 logger.AssertLogContains("Received TaskItemParam: 123 abc ; def ; ghi 789"); 103 } 104 105 /// <summary> 106 /// If I try to add a new item to a project, and my new item's Include has an unescaped semicolon 107 /// in it, then we shouldn't try to match it up against any existing wildcards. This is a really 108 /// bizarre scenario ... the caller probably meant to escape the semicolon. 109 /// </summary> 110 /// <owner>RGoel</owner> 111 [Test] AddNewItemWithSemicolon()112 public void AddNewItemWithSemicolon() 113 { 114 // ************************************ 115 // BEFORE 116 // ************************************ 117 string projectOriginalContents = @" 118 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 119 <ItemGroup> 120 <MyWildCard Include=`*.weirdo`/> 121 </ItemGroup> 122 </Project> 123 "; 124 125 126 // ************************************ 127 // AFTER 128 // ************************************ 129 string projectNewExpectedContents = @" 130 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 131 <ItemGroup> 132 <MyWildCard Include=`*.weirdo`/> 133 <MyWildCard Include=`foo;bar.weirdo`/> 134 </ItemGroup> 135 </Project> 136 "; 137 138 BuildItem newItem = AddItem.AddNewItemHelper(projectOriginalContents, 139 projectNewExpectedContents, "MyWildCard", "foo;bar.weirdo"); 140 141 Assertion.AssertEquals("Newly added item should have correct ItemName", "MyWildCard", newItem.Name); 142 Assertion.AssertEquals("Newly added item should have correct Include", "foo;bar.weirdo", newItem.Include); 143 } 144 145 /// <summary> 146 /// If I try to add a new item to a project, and my new item's Include has a property that 147 /// contains an unescaped semicolon in it, then we shouldn't try to match it up against any existing 148 /// wildcards. 149 /// </summary> 150 /// <owner>RGoel</owner> 151 [Test] AddNewItemWithPropertyContainingSemicolon()152 public void AddNewItemWithPropertyContainingSemicolon() 153 { 154 // ************************************ 155 // BEFORE 156 // ************************************ 157 string projectOriginalContents = @" 158 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 159 <PropertyGroup> 160 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 161 </PropertyGroup> 162 <ItemGroup> 163 <MyWildCard Include=`*.weirdo`/> 164 </ItemGroup> 165 </Project> 166 "; 167 168 169 // ************************************ 170 // AFTER 171 // ************************************ 172 string projectNewExpectedContents = @" 173 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 174 <PropertyGroup> 175 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 176 </PropertyGroup> 177 <ItemGroup> 178 <MyWildCard Include=`$(FilenameWithSemicolon).weirdo`/> 179 <MyWildCard Include=`*.weirdo`/> 180 </ItemGroup> 181 </Project> 182 "; 183 184 BuildItem newItem = AddItem.AddNewItemHelper(projectOriginalContents, 185 projectNewExpectedContents, "MyWildCard", "$(FilenameWithSemicolon).weirdo"); 186 187 Assertion.AssertEquals("Newly added item should have correct ItemName", "MyWildCard", newItem.Name); 188 Assertion.AssertEquals("Newly added item should have correct Include", "$(FilenameWithSemicolon).weirdo", newItem.Include); 189 } 190 191 /// <summary> 192 /// If I try to modify an item in a project, and my new item's Include has an unescaped semicolon 193 /// in it, then we shouldn't try to match it up against any existing wildcards. This is a really 194 /// bizarre scenario ... the caller probably meant to escape the semicolon. 195 /// </summary> 196 /// <owner>RGoel</owner> 197 [Test] ModifyItemIncludeSemicolon()198 public void ModifyItemIncludeSemicolon() 199 { 200 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 201 ModifyItem.CreateThreeWeirdoFilesHelper(); 202 203 // ************************************ 204 // BEFORE 205 // ************************************ 206 string projectOriginalContents = @" 207 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 208 209 <ItemGroup> 210 <MyWildcard Include=`*.weirdo` /> 211 </ItemGroup> 212 213 </Project> 214 "; 215 216 217 // ************************************ 218 // AFTER 219 // ************************************ 220 string projectNewExpectedContents = @" 221 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 222 223 <ItemGroup> 224 <MyWildcard Include=`a.weirdo` /> 225 <MyWildcard Include=`foo;bar.weirdo` /> 226 <MyWildcard Include=`c.weirdo` /> 227 </ItemGroup> 228 229 </Project> 230 "; 231 232 // Change b.weirdo to foo;bar.weirdo. 233 ModifyItem.ModifyItemIncludeHelper(projectOriginalContents, projectNewExpectedContents, 234 "b.weirdo", "foo;bar.weirdo"); 235 236 ModifyItem.CleanupWeirdoFilesHelper(); 237 } 238 239 /// <summary> 240 /// If I try to modify an item in a project, and my new item's Include has an escaped semicolon 241 /// in it, and it matches the existing wildcard, then we shouldn't need to modify the project file. 242 /// </summary> 243 /// <owner>RGoel</owner> 244 [Test] ModifyItemIncludeEscapedSemicolon()245 public void ModifyItemIncludeEscapedSemicolon() 246 { 247 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 248 ModifyItem.CreateThreeWeirdoFilesHelper(); 249 250 // ************************************ 251 // BEFORE 252 // ************************************ 253 string projectOriginalContents = @" 254 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 255 256 <ItemGroup> 257 <MyWildcard Include=`*.weirdo` /> 258 </ItemGroup> 259 260 </Project> 261 "; 262 263 264 // ************************************ 265 // AFTER 266 // ************************************ 267 string projectNewExpectedContents = @" 268 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 269 270 <ItemGroup> 271 <MyWildcard Include=`*.weirdo` /> 272 </ItemGroup> 273 274 </Project> 275 "; 276 277 // Change b.weirdo to foo;bar.weirdo. 278 ModifyItem.ModifyItemIncludeHelper(projectOriginalContents, projectNewExpectedContents, 279 "b.weirdo", "foo%253Bbar.weirdo"); 280 281 ModifyItem.CleanupWeirdoFilesHelper(); 282 } 283 284 /// <summary> 285 /// If I try to modify an item in a project, and my new item's Include has a property that 286 /// contains an unescaped semicolon in it, then we shouldn't try to match it up against any existing 287 /// wildcards. 288 /// </summary> 289 /// <owner>RGoel</owner> 290 [Test] ModifyItemAddPropertyContainingSemicolon()291 public void ModifyItemAddPropertyContainingSemicolon() 292 { 293 // Populate the project directory with three physical files on disk -- a.weirdo, b.weirdo, c.weirdo. 294 ModifyItem.CreateThreeWeirdoFilesHelper(); 295 296 // ************************************ 297 // BEFORE 298 // ************************************ 299 string projectOriginalContents = @" 300 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 301 302 <PropertyGroup> 303 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 304 </PropertyGroup> 305 306 <ItemGroup> 307 <MyWildcard Include=`*.weirdo` /> 308 </ItemGroup> 309 310 </Project> 311 "; 312 313 314 // ************************************ 315 // AFTER 316 // ************************************ 317 string projectNewExpectedContents = @" 318 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 319 320 <PropertyGroup> 321 <FilenameWithSemicolon>foo;bar</FilenameWithSemicolon> 322 </PropertyGroup> 323 324 <ItemGroup> 325 <MyWildcard Include=`a.weirdo` /> 326 <MyWildcard Include=`$(FileNameWithSemicolon).weirdo` /> 327 <MyWildcard Include=`c.weirdo` /> 328 </ItemGroup> 329 330 </Project> 331 "; 332 333 // Change b.weirdo to foo;bar.weirdo. 334 ModifyItem.ModifyItemIncludeHelper(projectOriginalContents, projectNewExpectedContents, 335 "b.weirdo", "$(FileNameWithSemicolon).weirdo"); 336 337 ModifyItem.CleanupWeirdoFilesHelper(); 338 } 339 340 /// <summary> 341 /// Make sure that character escaping works as expected when adding a new item that matches 342 /// an existing wildcarded item in the project file. 343 /// </summary> 344 /// <owner>RGoel</owner> 345 [Test] AddNewItemThatMatchesWildcard1()346 public void AddNewItemThatMatchesWildcard1() 347 { 348 // ************************************ 349 // BEFORE 350 // ************************************ 351 string projectOriginalContents = @" 352 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 353 <ItemGroup> 354 <MyWildCard Include=`*.weirdo`/> 355 </ItemGroup> 356 </Project> 357 "; 358 359 360 // ************************************ 361 // AFTER 362 // ************************************ 363 string projectNewExpectedContents = @" 364 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 365 <ItemGroup> 366 <MyWildCard Include=`*.weirdo`/> 367 </ItemGroup> 368 </Project> 369 "; 370 371 BuildItem newItem = AddItem.AddNewItemHelper(projectOriginalContents, 372 projectNewExpectedContents, "MyWildCard", "foo%253bbar.weirdo"); 373 374 Assertion.AssertEquals("Newly added item should have correct ItemName", "MyWildCard", newItem.Name); 375 Assertion.AssertEquals("Newly added item should have correct Include", "*.weirdo", newItem.Include); 376 Assertion.AssertEquals("Newly added item should have correct FinalItemSpec", "foo%253bbar.weirdo", newItem.FinalItemSpecEscaped); 377 Assertion.AssertEquals("Newly added item should have correct FinalItemSpec", "foo%3bbar.weirdo", newItem.FinalItemSpec); 378 } 379 380 /// <summary> 381 /// Make sure that character escaping works as expected when adding a new item that matches 382 /// an existing wildcarded item in the project file. 383 /// </summary> 384 /// <owner>RGoel</owner> 385 [Test] AddNewItemThatMatchesWildcard2()386 public void AddNewItemThatMatchesWildcard2() 387 { 388 // ************************************ 389 // BEFORE 390 // ************************************ 391 string projectOriginalContents = @" 392 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 393 <ItemGroup> 394 <MyWildCard Include=`*.AAA%253bBBB`/> 395 </ItemGroup> 396 </Project> 397 "; 398 399 400 // ************************************ 401 // AFTER 402 // ************************************ 403 string projectNewExpectedContents = @" 404 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 405 <ItemGroup> 406 <MyWildCard Include=`*.AAA%253bBBB`/> 407 </ItemGroup> 408 </Project> 409 "; 410 411 BuildItem newItem = AddItem.AddNewItemHelper(projectOriginalContents, 412 projectNewExpectedContents, "MyWildCard", "foobar.AAA%253bBBB"); 413 414 Assertion.AssertEquals("Newly added item should have correct ItemName", "MyWildCard", newItem.Name); 415 Assertion.AssertEquals("Newly added item should have correct Include", "*.AAA%253bBBB", newItem.Include); 416 Assertion.AssertEquals("Newly added item should have correct FinalItemSpec", "foobar.AAA%253bBBB", newItem.FinalItemSpecEscaped); 417 Assertion.AssertEquals("Newly added item should have correct FinalItemSpec", "foobar.AAA%3bBBB", newItem.FinalItemSpec); 418 } 419 420 /// <summary> 421 /// Make sure that all inferred task outputs (those that are determined without actually 422 /// executing the task) are left escaped when they become real items in the engine, and 423 /// they only get unescaped when fed into a subsequent task. 424 /// </summary> 425 /// <owner>RGoel</owner> 426 [Test] InferEscapedOutputsFromTask()427 public void InferEscapedOutputsFromTask() 428 { 429 string inputFile = ObjectModelHelpers.CreateTempFileOnDisk(""); 430 string outputFile = ObjectModelHelpers.CreateTempFileOnDisk(""); 431 432 try 433 { 434 MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(String.Format(@" 435 436 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 437 438 <Target Name=`GenerateResources` Inputs=`{0}` Outputs=`{1}`> 439 <NonExistentTask OutputResources=`aaa%253bbbb.resx; ccc%253bddd.resx`> 440 <Output ItemName=`Resource` TaskParameter=`OutputResources`/> 441 </NonExistentTask> 442 </Target> 443 444 <Target Name=`Build` DependsOnTargets=`GenerateResources`> 445 <Message Text=`Resources = @(Resource)`/> 446 </Target> 447 448 </Project> 449 450 ", inputFile, outputFile)); 451 452 logger.AssertLogContains("Resources = aaa%3bbbb.resx;ccc%3bddd.resx"); 453 } 454 finally 455 { 456 File.Delete(inputFile); 457 File.Delete(outputFile); 458 } 459 } 460 461 /// <summary> 462 /// Do an item transform, where the transform expression contains an unescaped semicolon as well 463 /// as an escaped percent sign. 464 /// </summary> 465 /// <owner>RGoel</owner> 466 [Test] ItemTransformContainingSemicolon()467 public void ItemTransformContainingSemicolon() 468 { 469 MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(@" 470 471 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 472 <ItemGroup> 473 <TextFile Include=`X.txt`/> 474 <TextFile Include=`Y.txt`/> 475 <TextFile Include=`Z.txt`/> 476 </ItemGroup> 477 <Target Name=`Build`> 478 <Message Text=`Transformed item list: '@(TextFile->'%(FileName);%(FileName)%253b%(FileName)%(Extension)',' ')'` /> 479 </Target> 480 </Project> 481 482 "); 483 484 logger.AssertLogContains("Transformed item list: 'X;X%3bX.txt Y;Y%3bY.txt Z;Z%3bZ.txt'"); 485 } 486 487 /// <summary> 488 /// Test that we can pass in global properties containing escaped characters. 489 /// </summary> 490 /// <owner>RGoel</owner> 491 [Test] GlobalPropertyWithEscapedCharacters()492 public void GlobalPropertyWithEscapedCharacters() 493 { 494 MockLogger logger = new MockLogger(); 495 Project project = ObjectModelHelpers.CreateInMemoryProject(@" 496 <Project ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 497 <Target Name=`Build`> 498 <Message Text=`MyGlobalProperty = '$(MyGlobalProperty)'` /> 499 </Target> 500 </Project> 501 ", logger); 502 503 project.GlobalProperties.SetProperty("MyGlobalProperty", "foo%253bbar"); 504 505 bool success = project.Build(null, null); 506 Assertion.Assert("Build failed. See Standard Out tab for details", success); 507 508 logger.AssertLogContains("MyGlobalProperty = 'foo%3bbar'"); 509 } 510 } 511 512 [TestFixture] 513 public class FullProjectsUsingMicrosoftCommonTargets 514 { 515 /// <summary> 516 /// Regression test for bug VSWhidbey 282492: 517 /// ESCAPING: Escaping in conditionals is broken. 518 /// </summary> 519 /// <owner>RGoel</owner> 520 [Test] SemicolonInConfiguration()521 public void SemicolonInConfiguration() 522 { 523 ObjectModelHelpers.DeleteTempProjectDirectory(); 524 525 // --------------------- 526 // Foo.csproj 527 // --------------------- 528 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 529 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 530 <PropertyGroup> 531 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 532 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 533 <OutputType>Library</OutputType> 534 <AssemblyName>ClassLibrary16</AssemblyName> 535 </PropertyGroup> 536 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'a%3bb%27c|AnyCPU' `> 537 <OutputPath>bin\a%3bb%27c\</OutputPath> 538 </PropertyGroup> 539 <ItemGroup> 540 <Reference Include=`System` /> 541 <Compile Include=`Class1.cs` /> 542 </ItemGroup> 543 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 544 </Project> 545 "); 546 547 // --------------------- 548 // Class1.cs 549 // --------------------- 550 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 551 namespace ClassLibrary16 552 { 553 public class Class1 554 { 555 } 556 } 557 "); 558 559 // Create a logger. 560 MockLogger logger = new MockLogger(); 561 562 Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory("foo.csproj", logger); 563 564 // Build the default targets using the Configuration "a;b'c". 565 project.GlobalProperties.SetProperty("Configuration", "a;b'c", true /* literal value */); 566 bool success = project.Build(null, null); 567 Assertion.Assert("Build failed. See Standard Out tab for details", success); 568 569 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"obj\a;b'c\ClassLibrary16.dll"); 570 ObjectModelHelpers.AssertFileExistsInTempProjectDirectory(@"bin\a;b'c\ClassLibrary16.dll"); 571 572 logger.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\a;b'c\ClassLibrary16.dll"))); 573 } 574 575 /// <summary> 576 /// Regression test for bug VSWhidbey 157204: 577 /// ESCAPING: CopyBuildTarget target fails if the output assembly name contains a semicolon or single-quote 578 /// </summary> 579 /// <owner>RGoel</owner> 580 [Test] SemicolonInAssemblyName()581 public void SemicolonInAssemblyName() 582 { 583 ObjectModelHelpers.DeleteTempProjectDirectory(); 584 585 // --------------------- 586 // Foo.csproj 587 // --------------------- 588 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 589 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 590 <PropertyGroup> 591 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 592 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 593 <OutputType>Library</OutputType> 594 <AssemblyName>Class%3bLibrary16</AssemblyName> 595 </PropertyGroup> 596 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 597 <OutputPath>bin\Debug\</OutputPath> 598 </PropertyGroup> 599 <ItemGroup> 600 <Reference Include=`System` /> 601 <Compile Include=`Class1.cs` /> 602 </ItemGroup> 603 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 604 </Project> 605 "); 606 607 // --------------------- 608 // Class1.cs 609 // --------------------- 610 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 611 namespace ClassLibrary16 612 { 613 public class Class1 614 { 615 } 616 } 617 "); 618 619 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 620 621 Assertion.Assert(@"Did not find expected file obj\debug\Class;Library16.dll", 622 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"obj\debug\Class;Library16.dll"))); 623 Assertion.Assert(@"Did not find expected file obj\debug\Class;Library16.pdb", 624 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"obj\debug\Class;Library16.pdb"))); 625 Assertion.Assert(@"Did not find expected file bin\debug\Class;Library16.dll", 626 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\debug\Class;Library16.dll"))); 627 Assertion.Assert(@"Did not find expected file bin\debug\Class;Library16.pdb", 628 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\debug\Class;Library16.pdb"))); 629 630 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\Class;Library16.dll"))); 631 } 632 633 /// <summary> 634 /// Regression test for bug VSWhidbey 157236: 635 /// ESCAPING: Conversion Issue: Properties with $(xxx) as literals are not being converted correctly 636 /// </summary> 637 /// <owner>RGoel</owner> 638 [Test] DollarSignInAssemblyName()639 public void DollarSignInAssemblyName() 640 { 641 ObjectModelHelpers.DeleteTempProjectDirectory(); 642 643 // --------------------- 644 // Foo.csproj 645 // --------------------- 646 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 647 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 648 <PropertyGroup> 649 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 650 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 651 <OutputType>Library</OutputType> 652 <AssemblyName>Class%24%28prop%29Library16</AssemblyName> 653 </PropertyGroup> 654 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 655 <OutputPath>bin\Debug\</OutputPath> 656 </PropertyGroup> 657 <ItemGroup> 658 <Reference Include=`System` /> 659 <Compile Include=`Class1.cs` /> 660 </ItemGroup> 661 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 662 </Project> 663 "); 664 665 // --------------------- 666 // Class1.cs 667 // --------------------- 668 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class1.cs", @" 669 namespace ClassLibrary16 670 { 671 public class Class1 672 { 673 } 674 } 675 "); 676 677 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 678 679 Assertion.Assert(@"Did not find expected file obj\debug\Class$(prop)Library16.dll", 680 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"obj\debug\Class$(prop)Library16.dll"))); 681 Assertion.Assert(@"Did not find expected file obj\debug\Class$(prop)Library16.pdb", 682 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"obj\debug\Class$(prop)Library16.pdb"))); 683 Assertion.Assert(@"Did not find expected file bin\debug\Class$(prop)Library16.dll", 684 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\debug\Class$(prop)Library16.dll"))); 685 Assertion.Assert(@"Did not find expected file bin\debug\Class$(prop)Library16.pdb", 686 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\debug\Class$(prop)Library16.pdb"))); 687 688 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\Class$(prop)Library16.dll"))); 689 } 690 691 /// <summary> 692 /// Regression test for bug VSWhidbey 146010 and related bugs. This is the case when one of the 693 /// source code files in the project has a filename containing a semicolon. 694 /// </summary> 695 /// <owner>RGoel</owner> 696 [Test] SemicolonInSourceCodeFilename()697 public void SemicolonInSourceCodeFilename() 698 { 699 ObjectModelHelpers.DeleteTempProjectDirectory(); 700 701 // --------------------- 702 // Foo.csproj 703 // --------------------- 704 ObjectModelHelpers.CreateFileInTempProjectDirectory("foo.csproj", @" 705 <Project DefaultTargets=`Build` ToolsVersion=`msbuilddefaulttoolsversion` xmlns=`msbuildnamespace`> 706 <PropertyGroup> 707 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 708 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 709 <OutputType>Library</OutputType> 710 <AssemblyName>ClassLibrary16</AssemblyName> 711 </PropertyGroup> 712 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 713 <OutputPath>bin\Debug\</OutputPath> 714 </PropertyGroup> 715 <ItemGroup> 716 <Reference Include=`System` /> 717 <Compile Include=`Class%3b1.cs` /> 718 </ItemGroup> 719 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 720 </Project> 721 "); 722 723 // --------------------- 724 // Class1.cs 725 // --------------------- 726 ObjectModelHelpers.CreateFileInTempProjectDirectory("Class;1.cs", @" 727 namespace ClassLibrary16 728 { 729 public class Class1 730 { 731 } 732 } 733 "); 734 735 MockLogger log = ObjectModelHelpers.BuildTempProjectFileExpectSuccess("foo.csproj"); 736 737 Assertion.Assert(@"Did not find expected file obj\debug\ClassLibrary16.dll", 738 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"obj\debug\ClassLibrary16.dll"))); 739 Assertion.Assert(@"Did not find expected file obj\debug\ClassLibrary16.pdb", 740 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"obj\debug\ClassLibrary16.pdb"))); 741 Assertion.Assert(@"Did not find expected file bin\debug\ClassLibrary16.dll", 742 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\debug\ClassLibrary16.dll"))); 743 Assertion.Assert(@"Did not find expected file bin\debug\ClassLibrary16.pdb", 744 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\debug\ClassLibrary16.pdb"))); 745 746 log.AssertLogContains(String.Format("foo -> {0}", Path.Combine(ObjectModelHelpers.TempProjectDir, @"bin\Debug\ClassLibrary16.dll"))); 747 } 748 749 /// <summary> 750 /// Build a .SLN file using MSBuild. The .SLN and the projects contained within 751 /// have all sorts of crazy characters in their name (courtesy of DanMose who apparently 752 /// just ran his fingers up and down the on the upper row of his keyboard :) ). There 753 /// is even a P2P reference between the two projects in the .SLN. 754 /// </summary> 755 /// <owner>RGoel</owner> 756 [Test] SolutionWithLotsaCrazyCharacters()757 public void SolutionWithLotsaCrazyCharacters() 758 { 759 if (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version35) == null) 760 { 761 Assert.Ignore(".NET Framework 3.5 is required to be installed for this test, but it is not installed."); 762 } 763 764 ObjectModelHelpers.DeleteTempProjectDirectory(); 765 766 // --------------------------------------------------------------------- 767 // Console;!@(foo)'^(Application1.sln 768 // --------------------------------------------------------------------- 769 ObjectModelHelpers.CreateFileInTempProjectDirectory( 770 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1.sln", 771 772 @"Microsoft Visual Studio Solution File, Format Version 10.00 773 # Visual Studio 2005 774 Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `Cons.ole;!@(foo)'^(Application1`, `Console;!@(foo)'^(Application1\Cons.ole;!@(foo)'^(Application1.csproj`, `{770F2381-8C39-49E9-8C96-0538FA4349A7}` 775 EndProject 776 Project(`{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}`) = `Class;!@(foo)'^(Library1`, `Class;!@(foo)'^(Library1\Class;!@(foo)'^(Library1.csproj`, `{0B4B78CC-C752-43C2-BE9A-319D20216129}` 777 EndProject 778 Global 779 GlobalSection(SolutionConfigurationPlatforms) = preSolution 780 Debug|Any CPU = Debug|Any CPU 781 Release|Any CPU = Release|Any CPU 782 EndGlobalSection 783 GlobalSection(ProjectConfigurationPlatforms) = postSolution 784 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 785 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Debug|Any CPU.Build.0 = Debug|Any CPU 786 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Release|Any CPU.ActiveCfg = Release|Any CPU 787 {770F2381-8C39-49E9-8C96-0538FA4349A7}.Release|Any CPU.Build.0 = Release|Any CPU 788 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 789 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Debug|Any CPU.Build.0 = Debug|Any CPU 790 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Release|Any CPU.ActiveCfg = Release|Any CPU 791 {0B4B78CC-C752-43C2-BE9A-319D20216129}.Release|Any CPU.Build.0 = Release|Any CPU 792 EndGlobalSection 793 GlobalSection(SolutionProperties) = preSolution 794 HideSolutionNode = FALSE 795 EndGlobalSection 796 EndGlobal 797 "); 798 799 // --------------------------------------------------------------------- 800 // Console;!@(foo)'^(Application1.csproj 801 // --------------------------------------------------------------------- 802 ObjectModelHelpers.CreateFileInTempProjectDirectory( 803 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\Cons.ole;!@(foo)'^(Application1.csproj", 804 805 @" 806 <Project DefaultTargets=`Build` ToolsVersion=`3.5` xmlns=`msbuildnamespace`> 807 <PropertyGroup> 808 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 809 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 810 <ProductVersion>8.0.50510</ProductVersion> 811 <SchemaVersion>2.0</SchemaVersion> 812 <ProjectGuid>{770F2381-8C39-49E9-8C96-0538FA4349A7}</ProjectGuid> 813 <OutputType>Exe</OutputType> 814 <AppDesignerFolder>Properties</AppDesignerFolder> 815 <RootNamespace>Console____foo____Application1</RootNamespace> 816 <AssemblyName>Console%3b!%40%28foo%29%27^%28Application1</AssemblyName> 817 </PropertyGroup> 818 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 819 <DebugSymbols>true</DebugSymbols> 820 <DebugType>full</DebugType> 821 <Optimize>false</Optimize> 822 <OutputPath>bin\Debug\</OutputPath> 823 <DefineConstants>DEBUG;TRACE</DefineConstants> 824 <ErrorReport>prompt</ErrorReport> 825 <WarningLevel>4</WarningLevel> 826 </PropertyGroup> 827 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Release|AnyCPU' `> 828 <DebugType>pdbonly</DebugType> 829 <Optimize>true</Optimize> 830 <OutputPath>bin\Release\</OutputPath> 831 <DefineConstants>TRACE</DefineConstants> 832 <ErrorReport>prompt</ErrorReport> 833 <WarningLevel>4</WarningLevel> 834 </PropertyGroup> 835 <ItemGroup> 836 <Reference Include=`System` /> 837 <Reference Include=`System.Data` /> 838 <Reference Include=`System.Xml` /> 839 </ItemGroup> 840 <ItemGroup> 841 <Compile Include=`Program.cs` /> 842 </ItemGroup> 843 <ItemGroup> 844 <ProjectReference Include=`..\Class%3b!%40%28foo%29%27^%28Library1\Class%3b!%40%28foo%29%27^%28Library1.csproj`> 845 <Project>{0B4B78CC-C752-43C2-BE9A-319D20216129}</Project> 846 <Name>Class%3b!%40%28foo%29%27^%28Library1</Name> 847 </ProjectReference> 848 </ItemGroup> 849 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 850 </Project> 851 "); 852 853 // --------------------------------------------------------------------- 854 // Program.cs 855 // --------------------------------------------------------------------- 856 ObjectModelHelpers.CreateFileInTempProjectDirectory( 857 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\Program.cs", 858 859 @" 860 using System; 861 using System.Collections.Generic; 862 using System.Text; 863 864 namespace Console____foo____Application1 865 { 866 class Program 867 { 868 static void Main(string[] args) 869 { 870 Class____foo____Library1.Class1 foo = new Class____foo____Library1.Class1(); 871 } 872 } 873 } 874 "); 875 876 // --------------------------------------------------------------------- 877 // Class;!@(foo)'^(Library1.csproj 878 // --------------------------------------------------------------------- 879 ObjectModelHelpers.CreateFileInTempProjectDirectory( 880 @"SLN;!@(foo)'^1\Class;!@(foo)'^(Library1\Class;!@(foo)'^(Library1.csproj", 881 882 @" 883 <Project DefaultTargets=`Build` ToolsVersion=`3.5` xmlns=`msbuildnamespace`> 884 <PropertyGroup> 885 <Configuration Condition=` '$(Configuration)' == '' `>Debug</Configuration> 886 <Platform Condition=` '$(Platform)' == '' `>AnyCPU</Platform> 887 <ProductVersion>8.0.50510</ProductVersion> 888 <SchemaVersion>2.0</SchemaVersion> 889 <ProjectGuid>{0B4B78CC-C752-43C2-BE9A-319D20216129}</ProjectGuid> 890 <OutputType>Library</OutputType> 891 <AppDesignerFolder>Properties</AppDesignerFolder> 892 <RootNamespace>Class____foo____Library1</RootNamespace> 893 <AssemblyName>Class%3b!%40%28foo%29%27^%28Library1</AssemblyName> 894 </PropertyGroup> 895 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' `> 896 <DebugSymbols>true</DebugSymbols> 897 <DebugType>full</DebugType> 898 <Optimize>false</Optimize> 899 <OutputPath>bin\Debug\</OutputPath> 900 <DefineConstants>DEBUG;TRACE</DefineConstants> 901 <ErrorReport>prompt</ErrorReport> 902 <WarningLevel>4</WarningLevel> 903 </PropertyGroup> 904 <PropertyGroup Condition=` '$(Configuration)|$(Platform)' == 'Release|AnyCPU' `> 905 <DebugType>pdbonly</DebugType> 906 <Optimize>true</Optimize> 907 <OutputPath>bin\Release\</OutputPath> 908 <DefineConstants>TRACE</DefineConstants> 909 <ErrorReport>prompt</ErrorReport> 910 <WarningLevel>4</WarningLevel> 911 </PropertyGroup> 912 <ItemGroup> 913 <Reference Include=`System` /> 914 <Reference Include=`System.Data` /> 915 <Reference Include=`System.Xml` /> 916 </ItemGroup> 917 <ItemGroup> 918 <Compile Include=`Class1.cs` /> 919 </ItemGroup> 920 <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets` /> 921 922 <!-- The old OM, which is what this solution is being built under, doesn't understand 923 BeforeTargets, so this test was failing, because _AssignManagedMetadata was set 924 up as a BeforeTarget for Build. Copied here so that build will return the correct 925 information again. --> 926 <Target Name=`BeforeBuild`> 927 <ItemGroup> 928 <BuiltTargetPath Include=`$(TargetPath)`> 929 <ManagedAssembly>$(ManagedAssembly)</ManagedAssembly> 930 </BuiltTargetPath> 931 </ItemGroup> 932 </Target> 933 </Project> 934 "); 935 936 // --------------------------------------------------------------------- 937 // Class1.cs 938 // --------------------------------------------------------------------- 939 ObjectModelHelpers.CreateFileInTempProjectDirectory( 940 @"SLN;!@(foo)'^1\Class;!@(foo)'^(Library1\Class1.cs", 941 942 @" 943 namespace Class____foo____Library1 944 { 945 public class Class1 946 { 947 } 948 } 949 "); 950 951 // Cons.ole;!@(foo)'^(Application1 952 string targetForFirstProject = "Cons_ole_!__foo__^_Application1"; 953 MockLogger log = ObjectModelHelpers.BuildTempProjectFileWithTargetsExpectSuccess(@"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1.sln", new string[] { targetForFirstProject }, new BuildPropertyGroup()); 954 955 Assertion.Assert(@"Did not find expected file Console;!@(foo)'^(Application1.exe", 956 File.Exists(Path.Combine(ObjectModelHelpers.TempProjectDir, 957 @"SLN;!@(foo)'^1\Console;!@(foo)'^(Application1\bin\debug\Console;!@(foo)'^(Application1.exe"))); 958 } 959 } 960 } 961