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