1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 using System; 5 using System.IO; 6 using System.Collections.Generic; 7 using System.Configuration; 8 using Microsoft.Win32; 9 using System.Text; 10 using NUnit.Framework; 11 using Microsoft.Build.BuildEngine; 12 using Microsoft.Build.BuildEngine.Shared; 13 14 namespace Microsoft.Build.UnitTests 15 { 16 /// <summary> 17 /// Unit tests for ToolsetReader class and its derived classes 18 /// </summary> 19 [TestFixture] 20 public class ToolsetReaderTests 21 { 22 // The registry key that is passed as the baseKey parameter to the ToolsetRegistryReader class 23 private RegistryKey testRegistryKey = null; 24 // Subkey "4.0" 25 private RegistryKey currentVersionRegistryKey = null; 26 // Subkey "ToolsVersions" 27 private RegistryKey toolsVersionsRegistryKey = null; 28 29 // Path to the registry key under HKCU 30 // Note that this is a test registry key created solely for unit testing. 31 private const string testRegistryPath = @"msbuildUnitTests"; 32 33 /// <summary> 34 /// Reset the testRegistryKey 35 /// </summary> 36 [SetUp] Setup()37 public void Setup() 38 { 39 TearDown(); 40 testRegistryKey = Registry.CurrentUser.CreateSubKey(testRegistryPath); 41 currentVersionRegistryKey = Registry.CurrentUser.CreateSubKey(testRegistryPath + "\\" + Constants.AssemblyVersion); 42 toolsVersionsRegistryKey = Registry.CurrentUser.CreateSubKey(testRegistryPath + "\\ToolsVersions"); 43 } 44 45 [TearDown] TearDown()46 public void TearDown() 47 { 48 ToolsetConfigurationReaderTestHelper.CleanUp(); 49 50 DeleteTestRegistryKey(); 51 } 52 53 /// <summary> 54 /// Helper class to delete the testRegistryKey tree. 55 /// </summary> DeleteTestRegistryKey()56 private void DeleteTestRegistryKey() 57 { 58 if (Registry.CurrentUser.OpenSubKey(testRegistryPath) != null) 59 { 60 Registry.CurrentUser.DeleteSubKeyTree(testRegistryPath); 61 } 62 } 63 64 /// <summary> 65 /// Test to make sure machine.config file has the section registered 66 /// and we are picking it up from there. 67 /// </summary> 68 [Test] GetToolsetDataFromConfiguration_SectionNotRegisteredInConfigFile()69 public void GetToolsetDataFromConfiguration_SectionNotRegisteredInConfigFile() 70 { 71 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 72 <configuration> 73 <configSections> 74 </configSections> 75 <msbuildToolsets> 76 <toolset toolsVersion=""2.0""> 77 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 78 </toolset> 79 </msbuildToolsets> 80 </configuration>"); 81 82 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 83 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 84 85 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 86 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 87 88 Assertion.AssertEquals(null, defaultToolsVersion); 89 Assertion.AssertEquals(0, values.Count); 90 } 91 92 #region "Reading from application configuration file tests" 93 94 /// <summary> 95 /// Tests that the data is correctly populated using function GetToolsetDataFromConfiguration 96 /// </summary> 97 [Test] 98 public void GetToolsetDataFromConfiguration_Basic() 99 { 100 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 101 <configuration> 102 <configSections> 103 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 104 </configSections> 105 <msbuildToolsets default=""2.0""> 106 <toolset toolsVersion=""2.0""> 107 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 108 </toolset> 109 <toolset toolsVersion=""3.5""> 110 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 111 </toolset> 112 </msbuildToolsets> 113 </configuration>"); 114 115 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 116 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 117 118 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 119 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 120 121 Assertion.AssertEquals("2.0", defaultToolsVersion); 122 Assertion.AssertEquals(2, values.Count); 123 Assertion.AssertEquals(0, values["2.0"].BuildProperties.Count); 124 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v2.0.x86ret", values["2.0"].ToolsPath); 125 Assertion.AssertEquals(0, values["3.5"].BuildProperties.Count); 126 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v3.5.x86ret", values["3.5"].ToolsPath); 127 } 128 129 /// <summary> 130 /// Relative paths can be used in a config file value 131 /// </summary> 132 [Test] 133 public void RelativePathInValue() 134 { 135 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 136 <configuration> 137 <configSections> 138 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 139 </configSections> 140 <msbuildToolsets default=""2.0""> 141 <toolset toolsVersion=""2.0""> 142 <property name=""MSBuildToolsPath"" value=""..\foo""/> 143 <!-- derelativization occurs before comparing toolspath and binpath --> 144 <property name=""MSBuildBinPath"" value=""..\.\foo""/> 145 </toolset> 146 <toolset toolsVersion=""3.0""> 147 <!-- properties are expanded before derelativization--> 148 <property name=""MSBuildBinPath"" value=""$(DotDotSlash)bar""/> 149 </toolset> 150 </msbuildToolsets> 151 </configuration>"); 152 153 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 154 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 155 156 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 157 BuildPropertyGroup pg = new BuildPropertyGroup(); 158 pg.SetProperty("DotDotSlash", @"..\"); 159 reader.ReadToolsets(values, new BuildPropertyGroup(), pg, true); 160 161 string expected1 = Path.GetFullPath(Path.Combine(FileUtilities.CurrentExecutableDirectory, @"..\foo")); 162 string expected2 = Path.GetFullPath(Path.Combine(FileUtilities.CurrentExecutableDirectory, @"..\bar")); 163 Console.WriteLine(values["2.0"].ToolsPath); 164 Assertion.AssertEquals(expected1, values["2.0"].ToolsPath); 165 Assertion.AssertEquals(expected2, values["3.0"].ToolsPath); 166 } 167 168 /// <summary> 169 /// Invalid relative path in msbuildbinpath value 170 /// </summary> 171 [Test] 172 public void InvalidRelativePath() 173 { 174 string invalidRelativePath = @"..\|invalid|"; 175 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 176 <configuration> 177 <configSections> 178 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 179 </configSections> 180 <msbuildToolsets default=""2.0""> 181 <toolset toolsVersion=""2.0""> 182 <property name=""MSBuildBinPath"" value=""" + invalidRelativePath + @"""/> 183 </toolset> 184 </msbuildToolsets> 185 </configuration>"); 186 187 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 188 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 189 190 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 191 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 192 193 // Don't crash (consistent with invalid absolute path) 194 Assertion.AssertEquals(invalidRelativePath, values["2.0"].ToolsPath); 195 } 196 197 /// <summary> 198 /// Tests the case where application configuration file is invalid 199 /// </summary> 200 [Test] 201 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 202 public void GetToolsetDataFromConfiguration_InvalidXmlFile() 203 { 204 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@"<INVALIDXML>"); 205 206 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 207 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 208 209 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 210 211 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 212 } 213 214 /// <summary> 215 /// Tests the case where application configuration file is invalid 216 /// </summary> 217 [Test] 218 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 219 public void GetToolsetDataFromConfiguration_InvalidConfigFile() 220 { 221 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 222 <configuration> 223 <configSections> 224 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 225 </configSections> 226 <msbuildToolsets> 227 <toolset toolsVersion=""2.0""> 228 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 229 </toolsVersion> 230 <SOMEINVALIDTAG/> 231 </msbuildToolsets> 232 </configuration>"); 233 234 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 235 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 236 237 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 238 239 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 240 } 241 242 /// <summary> 243 /// Tests the case where application configuration file is empty 244 /// </summary> 245 [Test] 246 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 247 public void GetToolsetDataFromConfiguration_FileEmpty() 248 { 249 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@""); 250 251 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 252 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 253 254 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 255 256 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 257 } 258 259 /// <summary> 260 /// Tests the case when ReadConfiguration throws exception 261 /// Make sure that we don't eat it and always throw ConfigurationErrorsException 262 /// </summary> 263 [Test] 264 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 265 public void GetToolsetDataFromConfiguration_ConfigurationExceptionThrown() 266 { 267 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@"", new ConfigurationException()); 268 269 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 270 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 271 272 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 273 274 // this should throw ... 275 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 276 } 277 278 /// <summary> 279 /// Tests the case when ReadConfiguration throws exception 280 /// Make sure that we don't eat it and always throw ConfigurationErrorsException 281 /// </summary> 282 [Test] 283 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 284 public void GetToolsetDataFromConfiguration_ConfigurationErrorsExceptionThrown() 285 { 286 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@"", new ConfigurationErrorsException()); 287 288 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 289 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 290 291 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 292 293 // this should throw ... 294 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 295 } 296 297 /// <summary> 298 /// Tests the case where default attribute is not specified in the config file 299 /// </summary> 300 [Test] 301 public void GetToolsetDataFromConfiguration_DefaultAttributeNotSpecified() 302 { 303 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 304 <configuration> 305 <configSections> 306 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 307 </configSections> 308 <msbuildToolsets> 309 <toolset toolsVersion=""2.0""> 310 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 311 </toolset> 312 </msbuildToolsets> 313 </configuration>"); 314 315 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 316 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 317 318 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 319 320 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 321 322 Assertion.AssertEquals(null, defaultToolsVersion); 323 Assertion.AssertEquals(1, values.Count); 324 Assertion.AssertEquals(0, values["2.0"].BuildProperties.Count); 325 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v2.0.x86ret", values["2.0"].ToolsPath); 326 } 327 328 /// <summary> 329 /// Default toolset has no toolsVersion element definition 330 /// </summary> 331 [Test] 332 public void GetToolsetDataFromConfiguration_DefaultToolsetUndefined() 333 { 334 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 335 <configuration> 336 <configSections> 337 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 338 </configSections> 339 <msbuildToolsets default=""nonexistent""> 340 <toolset toolsVersion=""2.0""> 341 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 342 </toolset> 343 </msbuildToolsets> 344 </configuration>"); 345 346 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 347 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 348 349 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 350 351 // Does not throw 352 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 353 } 354 355 /// <summary> 356 /// Tests the case where msbuildToolsets is not specified in the config file 357 /// Basically in the code we should be checking if config.GetSection("msbuildToolsets") returns a null 358 /// </summary> 359 [Test] 360 public void GetToolsetDataFromConfiguration_MSBuildToolsetsNodeNotPresent() 361 { 362 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 363 <configuration> 364 <configSections> 365 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 366 </configSections> 367 </configuration>"); 368 369 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 370 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 371 372 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 373 374 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 375 376 Assertion.AssertEquals(null, defaultToolsVersion); 377 Assertion.AssertEquals(0, values.Count); 378 } 379 380 /// <summary> 381 /// Tests that we handle empty MSBuildToolsets element correctly 382 /// </summary> 383 [Test] 384 public void GetToolsetDataFromConfiguration_EmptyMSBuildToolsetsNode() 385 { 386 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 387 <configuration> 388 <configSections> 389 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 390 </configSections> 391 <msbuildToolsets/> 392 </configuration>"); 393 394 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 395 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 396 397 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 398 399 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 400 401 Assertion.AssertEquals(null, defaultToolsVersion); 402 Assertion.AssertEquals(0, values.Count); 403 } 404 405 /// <summary> 406 /// Tests the case where only default ToolsVersion is specified in the application configuration file 407 /// </summary> 408 [Test] 409 public void GetToolsetDataFromConfiguration_OnlyDefaultSpecified() 410 { 411 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 412 <configuration> 413 <configSections> 414 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 415 </configSections> 416 <msbuildToolsets default=""2.0""/> 417 </configuration>"); 418 419 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 420 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 421 422 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 423 424 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 425 } 426 427 /// <summary> 428 /// Tests the case where only one ToolsVersion data is specified in the application configuration file 429 /// </summary> 430 [Test] 431 public void GetToolsetDataFromConfiguration_OneToolsVersionNode() 432 { 433 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 434 <configuration> 435 <configSections> 436 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 437 </configSections> 438 <msbuildToolsets default=""2.0""> 439 <toolset toolsVersion=""2.0""> 440 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 441 </toolset> 442 </msbuildToolsets> 443 </configuration>"); 444 445 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 446 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 447 448 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 449 450 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 451 452 Assertion.AssertEquals("2.0", defaultToolsVersion); 453 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v2.0.x86ret", values["2.0"].ToolsPath); 454 Assertion.AssertEquals(1, values.Count); 455 } 456 457 /// <summary> 458 /// Tests the case when an invalid value of ToolsVersion is specified 459 /// </summary> 460 [Test] 461 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 462 public void GetToolsetDataFromConfiguration_ToolsVersionIsEmptyString() 463 { 464 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 465 <configuration> 466 <configSections> 467 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 468 </configSections> 469 <msbuildToolsets default=""2.0""> 470 <toolset toolsVersion=""""> 471 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 472 </toolset> 473 <toolset toolsVersion=""3.5""> 474 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 475 </toolset> 476 </msbuildToolsets> 477 </configuration>"); 478 479 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 480 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 481 482 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 483 484 //this should throw ... 485 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 486 } 487 488 /// <summary> 489 /// If both MSBuildToolsPath and MSBuildBinPath are present, they must match 490 /// </summary> 491 [Test] 492 public void GetToolsetDataFromConfiguration_ToolsPathAndBinPathDiffer() 493 { 494 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 495 <configuration> 496 <configSections> 497 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 498 </configSections> 499 <msbuildToolsets default=""2.0""> 500 <toolset toolsVersion=""2.0""> 501 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 502 <property name=""MSBuildToolsPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 503 </toolset> 504 </msbuildToolsets> 505 </configuration>"); 506 507 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 508 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 509 510 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 511 512 //this should throw ... 513 bool caught = false; 514 try 515 { 516 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 517 } 518 catch (InvalidToolsetDefinitionException) 519 { 520 caught = true; 521 } 522 Assertion.Assert(caught); 523 } 524 525 /// <summary> 526 /// Tests the case when a blank value of PropertyName is specified in the config file 527 /// </summary> 528 [Test] 529 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 530 public void BlankPropertyNameInConfigFile() 531 { 532 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 533 <configuration> 534 <configSections> 535 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 536 </configSections> 537 <msbuildToolsets default=""2.0""> 538 <toolset toolsVersion=""2.0""> 539 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 540 <property name="""" value=""foo""/> 541 </toolset> 542 </msbuildToolsets> 543 </configuration>"); 544 545 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 546 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 547 548 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 549 550 //this should throw ... 551 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 552 } 553 554 /// <summary> 555 /// Tests the case when a blank property name is specified in the registry 556 /// </summary> 557 [Test] 558 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 559 public void BlankPropertyNameInRegistry() 560 { 561 RegistryKey rk = toolsVersionsRegistryKey.CreateSubKey("2.0"); 562 rk.SetValue("MSBuildBinPath", "someBinPath"); 563 rk.SetValue("", "foo"); 564 565 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 566 567 // Should throw ... 568 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 569 ( 570 values, 571 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 572 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 573 new BuildPropertyGroup(), 574 new BuildPropertyGroup(), 575 ToolsetDefinitionLocations.Registry 576 ); 577 } 578 579 /// <summary> 580 /// Tests the case when a blank property value is specified in the config file 581 /// </summary> 582 [Test] 583 public void BlankPropertyValueInConfigFile() 584 { 585 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 586 <configuration> 587 <configSections> 588 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 589 </configSections> 590 <msbuildToolsets default=""2.0""> 591 <toolset toolsVersion=""2.0""> 592 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 593 <property name=""foo"" value=""""/> 594 </toolset> 595 </msbuildToolsets> 596 </configuration>"); 597 598 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 599 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 600 601 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 602 603 //this should not throw ... 604 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 605 } 606 607 /// <summary> 608 /// Tests the case when a blank property value is specified in the registry 609 /// </summary> 610 [Test] 611 public void BlankPropertyValueInRegistry() 612 { 613 RegistryKey rk = toolsVersionsRegistryKey.CreateSubKey("2.0"); 614 rk.SetValue("MSBuildBinPath", "someBinPath"); 615 rk.SetValue("foo", ""); 616 617 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 618 619 // Should not throw ... 620 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 621 ( 622 values, 623 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 624 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 625 new BuildPropertyGroup(), 626 new BuildPropertyGroup(), 627 ToolsetDefinitionLocations.Registry 628 ); 629 } 630 631 /// <summary> 632 /// Tests the case when an invalid value of PropertyName is specified in the config file 633 /// </summary> 634 [Test] 635 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 636 public void InvalidPropertyNameInConfigFile() 637 { 638 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 639 <configuration> 640 <configSections> 641 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 642 </configSections> 643 <msbuildToolsets default=""2.0""> 644 <toolset toolsVersion=""2.0""> 645 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 646 <property name=""&"" value=""foo""/> 647 </toolset> 648 </msbuildToolsets> 649 </configuration>"); 650 651 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 652 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 653 654 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 655 656 //this should throw ... 657 reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 658 } 659 660 /// <summary> 661 /// Tests the case when an invalid value of PropertyName is specified in the registry 662 /// </summary> 663 [Test] 664 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 665 public void InvalidPropertyNameInRegistry() 666 { 667 RegistryKey rk = toolsVersionsRegistryKey.CreateSubKey("2.0"); 668 rk.SetValue("MSBuildBinPath", "someBinPath"); 669 rk.SetValue("foo|bar", "x"); 670 671 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 672 673 // Should throw ... 674 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 675 ( 676 values, 677 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 678 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 679 new BuildPropertyGroup(), 680 new BuildPropertyGroup(), 681 ToolsetDefinitionLocations.Registry 682 ); 683 } 684 685 /// <summary> 686 /// Tests that empty string is an invalid value for MSBuildBinPath 687 /// </summary> 688 [Test] 689 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 690 public void GetToolsetDataFromConfiguration_PropertyValueIsEmptyString1() 691 { 692 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 693 <configuration> 694 <configSections> 695 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 696 </configSections> 697 <msbuildToolsets default=""2.0""> 698 <toolset toolsVersion=""2.0""> 699 <property name=""MSBuildBinPath"" value=""""/> 700 </toolset> 701 </msbuildToolsets> 702 </configuration>"); 703 704 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 705 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 706 707 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 708 709 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 710 711 Assertion.AssertEquals(1, values.Count); 712 Assertion.AssertEquals(0, values["2.0"].BuildProperties.Count); 713 Assertion.AssertEquals(String.Empty, values["2.0"].ToolsPath); 714 } 715 716 /// <summary> 717 /// Tests that empty string is a valid property value for an arbitrary property 718 /// </summary> 719 [Test] 720 public void GetToolsetDataFromConfiguration_PropertyValueIsEmptyString2() 721 { 722 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 723 <configuration> 724 <configSections> 725 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 726 </configSections> 727 <msbuildToolsets default=""2.0""> 728 <toolset toolsVersion=""2.0""> 729 <property name=""MSBuildToolsPath"" value=""xxx""/> 730 <property name=""foo"" value=""""/> 731 </toolset> 732 </msbuildToolsets> 733 </configuration>"); 734 735 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 736 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 737 738 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 739 740 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 741 742 Assertion.AssertEquals(1, values.Count); 743 Assertion.AssertEquals(1, values["2.0"].BuildProperties.Count); 744 Assertion.AssertEquals(String.Empty, values["2.0"].BuildProperties["foo"].Value); 745 } 746 747 /// <summary> 748 /// Tests that any escaped xml in config file, is treated well 749 /// Note that this comes for free with the current implementation using the 750 /// framework api to access section in the config file 751 /// </summary> 752 [Test] 753 public void GetToolsetDataFromConfiguration_XmlEscapedCharacters() 754 { 755 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 756 <configuration> 757 <configSections> 758 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 759 </configSections> 760 <msbuildToolsets default=""2>.0""> 761 <toolset toolsVersion=""2>.0""> 762 <property name=""MSBuildBinPath"" value=""x""/> 763 <property name=""foo"" value=""some>value""/> 764 </toolset> 765 </msbuildToolsets> 766 </configuration>"); 767 768 ToolsetReader reader = new ToolsetConfigurationReader(new ReadApplicationConfiguration( 769 ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)); 770 771 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 772 773 string defaultToolsVersion = reader.ReadToolsets(values, new BuildPropertyGroup(), new BuildPropertyGroup(), true); 774 775 Assertion.AssertEquals("2>.0", defaultToolsVersion); 776 Assertion.AssertEquals(1, values.Count); 777 Assertion.AssertEquals(@"some>value", values["2>.0"].BuildProperties["foo"].Value); 778 } 779 #endregion 780 781 #region "GetToolsetData tests" 782 783 /// <summary> 784 /// Tests the case where registry and config file contains different toolsVersion 785 /// </summary> 786 [Test] 787 public void GetToolsetData_NoConflict() 788 { 789 // Set up registry with two tools versions and one property each 790 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 791 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 792 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 793 RegistryKey key2 = toolsVersionsRegistryKey.CreateSubKey("3.5"); 794 key2.SetValue("MSBuildBinPath", @"D:\somepath2"); 795 796 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 797 <configuration> 798 <configSections> 799 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 800 </configSections> 801 <msbuildToolsets default=""4.5""> 802 <toolset toolsVersion=""4.5""> 803 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 804 </toolset> 805 <toolset toolsVersion=""5.0""> 806 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 807 </toolset> 808 </msbuildToolsets> 809 </configuration>"); 810 811 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 812 813 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 814 ( 815 values, 816 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 817 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 818 new BuildPropertyGroup(), 819 new BuildPropertyGroup(), 820 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 821 ); 822 823 // Verifications 824 Assertion.AssertEquals(4, values.Count); 825 Assertion.AssertEquals("4.5", defaultToolsVersion); 826 Assertion.AssertEquals(@"D:\somepath", values["2.0"].ToolsPath); 827 Assertion.AssertEquals(@"D:\somepath2", values["3.5"].ToolsPath); 828 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v2.0.x86ret", values["4.5"].ToolsPath); 829 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v3.5.x86ret", values["5.0"].ToolsPath); 830 } 831 832 /// <summary> 833 /// Tests that ToolsetInitialization are respected. 834 /// </summary> 835 [Test] 836 public void ToolsetInitializationFlagsSetToNone() 837 { 838 // Set up registry with two tools versions and one property each 839 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 840 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 841 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 842 RegistryKey key2 = testRegistryKey.CreateSubKey("3.5"); 843 key2.SetValue("MSBuildBinPath", @"D:\somepath2"); 844 845 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 846 <configuration> 847 <configSections> 848 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 849 </configSections> 850 <msbuildToolsets default=""4.5""> 851 <toolset toolsVersion=""4.5""> 852 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 853 </toolset> 854 <toolset toolsVersion=""5.0""> 855 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 856 </toolset> 857 </msbuildToolsets> 858 </configuration>"); 859 860 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 861 862 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 863 ( 864 values, 865 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 866 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 867 new BuildPropertyGroup(), 868 new BuildPropertyGroup(), 869 ToolsetDefinitionLocations.None 870 ); 871 872 // Verifications 873 Assertion.AssertEquals(1, values.Count); 874 875 string expectedDefault = "2.0"; 876 if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) 877 { 878 expectedDefault = "4.0"; 879 } 880 881 Assertion.AssertEquals(expectedDefault, defaultToolsVersion); 882 } 883 884 /// <summary> 885 /// Tests that ToolsetInitialization are respected. 886 /// </summary> 887 [Test] 888 public void ToolsetInitializationFlagsSetToRegistry() 889 { 890 // Set up registry with two tools versions and one property each 891 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 892 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 893 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 894 RegistryKey key2 = toolsVersionsRegistryKey.CreateSubKey("3.5"); 895 key2.SetValue("MSBuildBinPath", @"D:\somepath2"); 896 897 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 898 <configuration> 899 <configSections> 900 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 901 </configSections> 902 <msbuildToolsets default=""4.5""> 903 <toolset toolsVersion=""4.5""> 904 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 905 </toolset> 906 <toolset toolsVersion=""5.0""> 907 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 908 </toolset> 909 </msbuildToolsets> 910 </configuration>"); 911 912 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 913 914 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 915 ( 916 values, 917 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 918 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 919 new BuildPropertyGroup(), 920 new BuildPropertyGroup(), 921 ToolsetDefinitionLocations.Registry 922 ); 923 924 // Verifications 925 Assertion.AssertEquals(2, values.Count); 926 Assertion.AssertEquals("2.0", defaultToolsVersion); 927 Assertion.AssertEquals(@"D:\somepath", values["2.0"].ToolsPath); 928 Assertion.AssertEquals(@"D:\somepath2", values["3.5"].ToolsPath); 929 } 930 931 [Test] 932 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 933 public void ThrowOnNonStringRegistryValueTypes() 934 { 935 RegistryKey rk = toolsVersionsRegistryKey.CreateSubKey("2.0"); 936 rk.SetValue("MSBuildBinPath", "someBinPath"); 937 938 // Non-string 939 rk.SetValue("QuadWordValue", 42, RegistryValueKind.QWord); 940 941 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 942 943 // Should throw ... 944 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 945 ( 946 values, 947 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 948 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 949 new BuildPropertyGroup(), 950 new BuildPropertyGroup(), 951 ToolsetDefinitionLocations.Registry 952 ); 953 } 954 955 [Test] 956 public void PropertiesInRegistryCannotReferToOtherPropertiesInRegistry() 957 { 958 RegistryKey rk = toolsVersionsRegistryKey.CreateSubKey("2.0"); 959 rk.SetValue("MSBuildBinPath", "c:\\x$(p1)"); 960 rk.SetValue("p0", "$(p1)"); 961 rk.SetValue("p1", "v"); 962 rk.SetValue("p2", "$(p1)"); 963 rk.SetValue("MSBuildToolsPath", "c:\\x$(p1)"); 964 965 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 966 967 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 968 ( 969 values, 970 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 971 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 972 new BuildPropertyGroup(), 973 new BuildPropertyGroup(), 974 ToolsetDefinitionLocations.Registry 975 ); 976 977 Assertion.AssertEquals("", values["2.0"].BuildProperties["p0"].Value); 978 Assertion.AssertEquals("v", values["2.0"].BuildProperties["p1"].Value); 979 Assertion.AssertEquals("", values["2.0"].BuildProperties["p2"].Value); 980 Assertion.AssertEquals("c:\\x", values["2.0"].ToolsPath); 981 } 982 983 /// <summary> 984 /// Tests that ToolsetInitialization are respected. 985 /// </summary> 986 [Test] 987 public void ToolsetInitializationFlagsSetToConfigurationFile() 988 { 989 // Set up registry with two tools versions and one property each 990 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 991 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 992 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 993 RegistryKey key2 = toolsVersionsRegistryKey.CreateSubKey("3.5"); 994 key2.SetValue("MSBuildBinPath", @"D:\somepath2"); 995 996 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 997 <configuration> 998 <configSections> 999 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1000 </configSections> 1001 <msbuildToolsets default=""4.5""> 1002 <toolset toolsVersion=""4.5""> 1003 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 1004 </toolset> 1005 <toolset toolsVersion=""5.0""> 1006 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 1007 </toolset> 1008 </msbuildToolsets> 1009 </configuration>"); 1010 1011 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1012 1013 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1014 ( 1015 values, 1016 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1017 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1018 new BuildPropertyGroup(), 1019 new BuildPropertyGroup(), 1020 ToolsetDefinitionLocations.ConfigurationFile 1021 ); 1022 1023 // Verifications 1024 Assertion.AssertEquals(2, values.Count); 1025 Assertion.AssertEquals("4.5", defaultToolsVersion); 1026 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v2.0.x86ret", values["4.5"].ToolsPath); 1027 Assertion.AssertEquals(@"D:\windows\Microsoft.NET\Framework\v3.5.x86ret", values["5.0"].ToolsPath); 1028 } 1029 1030 /// <summary> 1031 /// Properties in the configuration file may refer to a registry location by using the syntax for example 1032 /// "$(Registry:HKEY_LOCAL_MACHINE\Software\Vendor\Tools@TaskLocation)", where "HKEY_LOCAL_MACHINE\Software\Vendor\Tools" is the key and 1033 /// "TaskLocation" is the name of the value. The name of the value and the preceding "@" may be omitted if 1034 /// the default value is desired. 1035 /// </summary> 1036 [Test] 1037 public void PropertyInConfigurationFileReferencesRegistryLocation() 1038 { 1039 // Registry Read 1040 RegistryKey key1 = Registry.CurrentUser.CreateSubKey(@"Software\Vendor\Tools"); 1041 key1.SetValue("TaskLocation", @"somePathToTasks"); 1042 key1.SetValue("TargetsLocation", @"D:\somePathToTargets"); 1043 key1.SetValue("SchemaLocation", @"Schemas"); 1044 key1.SetValue(null, @"D:\somePathToDefault"); //this sets the default value for this key 1045 1046 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1047 <configuration> 1048 <configSections> 1049 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1050 </configSections> 1051 <msbuildToolsets default=""2.0""> 1052 <toolset toolsVersion=""2.0""> 1053 <property name=""MSBuildBinPath"" value=""D:\$(Registry:HKEY_CURRENT_USER\Software\Vendor\Tools@TaskLocation)""/> 1054 <property name=""p1"" value=""$(p2)$(REGISTRY:HKEY_CURRENT_USER\Software\Vendor\Tools)""/> 1055 <property name=""p2"" value=""$(p1)\$(Registry:hkey_current_user\Software\Vendor\Tools@TaskLocation)\$(Registry:HKEY_CURRENT_USER\Software\Vendor\Tools@SchemaLocation)\2.0""/> 1056 </toolset> 1057 </msbuildToolsets> 1058 </configuration>"); 1059 1060 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1061 1062 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1063 ( 1064 values, 1065 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1066 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1067 new BuildPropertyGroup(), 1068 new BuildPropertyGroup(), 1069 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1070 ); 1071 1072 Assertion.AssertEquals(1, values.Count); 1073 Assertion.AssertEquals(@"D:\somePathToTasks", values["2.0"].ToolsPath); 1074 Assertion.AssertEquals(2, values["2.0"].BuildProperties.Count); 1075 Assertion.AssertEquals(@"D:\somePathToDefault", values["2.0"].BuildProperties["p1"].Value); 1076 Assertion.AssertEquals(@"D:\somePathToDefault\somePathToTasks\Schemas\2.0", values["2.0"].BuildProperties["p2"].Value); 1077 1078 Registry.CurrentUser.DeleteSubKeyTree(@"Software\Vendor"); 1079 } 1080 1081 [Test] 1082 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1083 public void ToolsPathInRegistryHasInvalidPathChars() 1084 { 1085 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 1086 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1087 key1.SetValue("MSBuildBinPath", @"D:\some\foo|bar\path\"); 1088 1089 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1090 1091 // should throw... 1092 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1093 ( 1094 values, 1095 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1096 null, 1097 new BuildPropertyGroup(), 1098 new BuildPropertyGroup(), 1099 ToolsetDefinitionLocations.Registry 1100 ); 1101 } 1102 1103 [Test] 1104 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1105 public void SamePropertyDefinedMultipleTimesForSingleToolsVersionInConfigurationFile() 1106 { 1107 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1108 <configuration> 1109 <configSections> 1110 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1111 </configSections> 1112 <msbuildToolsets default=""2.0""> 1113 <toolset toolsVersion=""2.0""> 1114 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1115 <property name=""p1"" value=""another""/> 1116 <property name=""MSBuildBinPath"" value=""C:\$(p1)\folder""/> 1117 <property name=""p1"" value=""newValue""/> 1118 </toolset> 1119 </msbuildToolsets> 1120 </configuration>"); 1121 1122 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1123 1124 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1125 ( 1126 values, 1127 null, 1128 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1129 new BuildPropertyGroup(), 1130 new BuildPropertyGroup(), 1131 ToolsetDefinitionLocations.ConfigurationFile 1132 ); 1133 } 1134 1135 [Test] 1136 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1137 public void SamePropertyDifferentCaseDefinedMultipleTimesForSingleToolsVersionInConfigurationFile() 1138 { 1139 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1140 <configuration> 1141 <configSections> 1142 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1143 </configSections> 1144 <msbuildToolsets default=""2.0""> 1145 <toolset toolsVersion=""2.0""> 1146 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1147 <property name=""p1"" value=""another""/> 1148 <property name=""mSbUiLdBiNpAtH"" value=""C:\$(p1)\folder""/> 1149 <property name=""P1"" value=""newValue""/> 1150 </toolset> 1151 </msbuildToolsets> 1152 </configuration>"); 1153 1154 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1155 1156 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1157 ( 1158 values, 1159 null, 1160 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1161 new BuildPropertyGroup(), 1162 new BuildPropertyGroup(), 1163 ToolsetDefinitionLocations.ConfigurationFile 1164 ); 1165 } 1166 1167 [Test] 1168 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1169 public void SameToolsVersionDefinedMultipleTimesInConfigurationFile() 1170 { 1171 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1172 <configuration> 1173 <configSections> 1174 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1175 </configSections> 1176 <msbuildToolsets default=""2.0""> 1177 <toolset toolsVersion=""2.0""> 1178 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1179 <property name=""p1"" value=""another""/> 1180 </toolset> 1181 <toolset toolsVersion=""3.5""> 1182 <property name=""MSBuildBinPath"" value=""D:\folder""/> 1183 <property name=""p2"" value=""anotherValue""/> 1184 </toolset> 1185 <toolset toolsVersion=""2.0""> 1186 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1187 <property name=""p1"" value=""another""/> 1188 </toolset> 1189 </msbuildToolsets> 1190 </configuration>"); 1191 1192 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1193 1194 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1195 ( 1196 values, 1197 null, 1198 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1199 new BuildPropertyGroup(), 1200 new BuildPropertyGroup(), 1201 ToolsetDefinitionLocations.ConfigurationFile 1202 ); 1203 } 1204 1205 [Test] 1206 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1207 public void SameToolsVersionDifferentCaseDefinedMultipleTimesInConfigurationFile() 1208 { 1209 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1210 <configuration> 1211 <configSections> 1212 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1213 </configSections> 1214 <msbuildToolsets default=""2.0""> 1215 <toolset toolsVersion=""DevDiv""> 1216 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1217 <property name=""p1"" value=""another""/> 1218 </toolset> 1219 <toolset toolsVersion=""3.5""> 1220 <property name=""MSBuildBinPath"" value=""D:\folder""/> 1221 <property name=""p2"" value=""anotherValue""/> 1222 </toolset> 1223 <toolset toolsVersion=""DEVDIV""> 1224 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1225 <property name=""p1"" value=""another""/> 1226 </toolset> 1227 </msbuildToolsets> 1228 </configuration>"); 1229 1230 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1231 1232 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1233 ( 1234 values, 1235 null, 1236 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1237 new BuildPropertyGroup(), 1238 new BuildPropertyGroup(), 1239 ToolsetDefinitionLocations.ConfigurationFile 1240 ); 1241 } 1242 1243 [Test] 1244 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1245 public void CannotSetReservedPropertyInConfigFile() 1246 { 1247 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1248 <configuration> 1249 <configSections> 1250 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1251 </configSections> 1252 <msbuildToolsets default=""2.0""> 1253 <toolset toolsVersion=""2.0""> 1254 <property name=""MSBuildBinPath"" value=""D:\some\folder\on\disk""/> 1255 <property name=""MSBuildProjectFile"" value=""newValue""/> 1256 </toolset> 1257 </msbuildToolsets> 1258 </configuration>"); 1259 1260 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1261 1262 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1263 ( 1264 values, 1265 null, 1266 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1267 new BuildPropertyGroup(), 1268 new BuildPropertyGroup(), 1269 ToolsetDefinitionLocations.ConfigurationFile 1270 ); 1271 } 1272 1273 [Test] 1274 [ExpectedException(typeof(InvalidToolsetDefinitionException))] 1275 public void CannotSetReservedPropertyInRegistry() 1276 { 1277 // Registry Read 1278 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1279 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 1280 key1.SetValue("MSBuildProjectFile", @"SomeRegistryValue"); 1281 1282 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1283 1284 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1285 ( 1286 values, 1287 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1288 null, 1289 new BuildPropertyGroup(), 1290 new BuildPropertyGroup(), 1291 ToolsetDefinitionLocations.Registry 1292 ); 1293 } 1294 1295 /// <summary> 1296 /// Properties defined in previously processed toolset definitions should 1297 /// not affect the evaluation of subsequent toolset definitions. 1298 /// </summary> 1299 [Test] 1300 public void NoInterferenceBetweenToolsetDefinitions() 1301 { 1302 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1303 <configuration> 1304 <configSections> 1305 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1306 </configSections> 1307 <msbuildToolsets default=""2.0""> 1308 <toolset toolsVersion=""2.0""> 1309 <property name=""MSBuildBinPath"" value=""D:\20\some\folder\on\disk""/> 1310 <property name=""p1"" value=""another""/> 1311 <property name=""p4"" value=""fourth$(p3)Value"" /> 1312 </toolset> 1313 <toolset toolsVersion=""3.5""> 1314 <property name=""MSBuildBinPath"" value=""D:\35\some\folder\on\disk""/> 1315 <property name=""p2"" value=""some$(p1)value""/> 1316 <property name=""p3"" value=""propertyValue""/> 1317 </toolset> 1318 </msbuildToolsets> 1319 </configuration>"); 1320 1321 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1322 1323 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1324 ( 1325 values, 1326 null, 1327 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1328 new BuildPropertyGroup(), 1329 new BuildPropertyGroup(), 1330 ToolsetDefinitionLocations.ConfigurationFile 1331 ); 1332 1333 Assertion.AssertEquals(2, values.Count); 1334 1335 Assertion.AssertEquals(@"D:\20\some\folder\on\disk", values["2.0"].ToolsPath); 1336 Assertion.AssertEquals(2, values["2.0"].BuildProperties.Count); 1337 Assertion.AssertEquals(@"another", values["2.0"].BuildProperties["p1"].Value); 1338 Assertion.AssertEquals(@"fourthValue", values["2.0"].BuildProperties["p4"].Value); 1339 1340 Assertion.AssertEquals(@"D:\35\some\folder\on\disk", values["3.5"].ToolsPath); 1341 Assertion.AssertEquals(2, values["3.5"].BuildProperties.Count); 1342 Assertion.AssertEquals(@"somevalue", values["3.5"].BuildProperties["p2"].Value); 1343 Assertion.AssertEquals(@"propertyValue", values["3.5"].BuildProperties["p3"].Value); 1344 } 1345 1346 /// <summary> 1347 /// Properties in the configuration file may refer to a registry location by using the syntax for example 1348 /// "$(Registry:HKEY_LOCAL_MACHINE\Software\Vendor\Tools@TaskLocation)", where "HKEY_LOCAL_MACHINE\Software\Vendor\Tools" is the key and 1349 /// "TaskLocation" is the name of the value. The name of the value and the preceding "@" may be omitted if 1350 /// the default value is desired. 1351 /// </summary> 1352 1353 [Test] 1354 public void ConfigFileInvalidRegistryExpression1() 1355 { 1356 // No location 1357 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:)""/>"); 1358 } 1359 1360 [Test] 1361 public void ConfigFileInvalidRegistryExpression2() 1362 { 1363 // Bogus key expression 1364 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:__bogus__)""/>"); 1365 } 1366 1367 [Test] 1368 public void ConfigFileInvalidRegistryExpression3() 1369 { 1370 // No registry location just @ 1371 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:@)""/>"); 1372 } 1373 1374 [Test] 1375 public void ConfigFileInvalidRegistryExpression4() 1376 { 1377 // Double @ 1378 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:HKEY_CURRENT_USER\Software\Vendor\Tools@@TaskLocation)""/>"); 1379 } 1380 1381 [Test] 1382 public void ConfigFileInvalidRegistryExpression5() 1383 { 1384 // Trailing @ 1385 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:HKEY_CURRENT_USER\Software\Vendor\Tools@TaskLocation@)""/>"); 1386 } 1387 1388 [Test] 1389 public void ConfigFileInvalidRegistryExpression6() 1390 { 1391 // Leading @ 1392 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:@HKEY_CURRENT_USER\Software\Vendor\Tools@TaskLocation)""/>"); 1393 } 1394 1395 [Test] 1396 public void ConfigFileInvalidRegistryExpression7() 1397 { 1398 // Bogus hive 1399 ConfigFileInvalidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:BOGUS_HIVE\Software\Vendor\Tools@TaskLocation)""/>"); 1400 } 1401 1402 [Test] 1403 public void ConfigFileStringEmptyRegistryExpression1() 1404 { 1405 // Regular undefined property beginning with "Registry" 1406 ConfigFileValidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry)""/>", 1407 String.Empty); 1408 } 1409 1410 [Test] 1411 public void ConfigFileStringEmptyRegistryExpression2() 1412 { 1413 // Nonexistent key 1414 ConfigFileValidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:HKEY_CURRENT_USER\Nonexistent_Key\Software\Vendor\Tools@TaskLocation)""/>", 1415 String.Empty); 1416 } 1417 1418 [Test] 1419 public void ConfigFileNonPropertyRegistryExpression1() 1420 { 1421 // Property not terminated with paren, does not look like property 1422 ConfigFileValidRegistryExpressionHelper(@"<property name=""p"" value=""$(Registry:HKEY_CURRENT_USER\Software\Vendor\Tools@TaskLocation""/>", 1423 @"$(Registry:HKEY_CURRENT_USER\Software\Vendor\Tools@TaskLocation"); 1424 } 1425 1426 [Test] 1427 public void ConfigFileNonPropertyRegistryExpression2() 1428 { 1429 // Missing colon, looks like regular property (admittedly with invalid property name chars, but we don't 1430 // error for that today) 1431 ConfigFileValidRegistryExpressionHelper(@"<property name=""p"" value=""$(RegistryHKEY_CURRENT_USER\Software\Vendor\Tools@@TaskLocation)""/>", 1432 String.Empty); 1433 } 1434 1435 [Test] 1436 public void ConfigFileItemExpressionsDoNotExpandInConfigurationProperties() 1437 { 1438 // Expect that item expressions such as '@(SomeItem)' are not evaluated in any way, e.g., they are treated literally 1439 ConfigFileValidRegistryExpressionHelper(@"<property name=""p"" value=""@(SomeItem)""/>", 1440 @"@(SomeItem)"); 1441 } 1442 1443 [Test] 1444 public void RegistryInvalidRegistryExpression1() 1445 { 1446 // Bogus key expression 1447 RegistryInvalidRegistryExpressionHelper("$(Registry:__bogus__)"); 1448 } 1449 1450 [Test] 1451 public void RegistryValidRegistryExpression1() 1452 { 1453 // Regular undefined property beginning with "Registry" 1454 RegistryValidRegistryExpressionHelper("$(Registry)", String.Empty); 1455 } 1456 1457 [Test] 1458 public void RegistryValidRegistryExpressionRecursive() 1459 { 1460 // Property pointing to itself - should not hang :-) 1461 RegistryValidRegistryExpressionHelper 1462 (@"$(Registry:HKEY_CURRENT_USER\" + testRegistryPath + @"\ToolsVersions\2.0@p)", 1463 @"$(Registry:HKEY_CURRENT_USER\" + testRegistryPath + @"\ToolsVersions\2.0@p)"); 1464 } 1465 1466 private void RegistryInvalidRegistryExpressionHelper(string propertyExpression) 1467 { 1468 bool caught = false; 1469 try 1470 { 1471 // this should throw... 1472 RegistryValidRegistryExpressionHelper(propertyExpression, String.Empty); 1473 } 1474 catch (InvalidToolsetDefinitionException ex) 1475 { 1476 Console.WriteLine(ex.Message); 1477 caught = true; 1478 } 1479 1480 Assertion.AssertEquals(true, caught); 1481 } 1482 1483 private void RegistryValidRegistryExpressionHelper(string propertyExpression, string expectedValue) 1484 { 1485 // Registry Read 1486 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 1487 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1488 key1.SetValue("MSBuildBinPath", "xxxx"); 1489 key1.SetValue("p", propertyExpression); 1490 1491 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1492 1493 ToolsetReader.ReadAllToolsets 1494 ( 1495 values, 1496 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1497 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1498 new BuildPropertyGroup(), 1499 new BuildPropertyGroup(), 1500 ToolsetDefinitionLocations.Registry 1501 ); 1502 1503 Assertion.AssertEquals(1, values.Count); 1504 Assertion.AssertEquals(expectedValue, values["2.0"].BuildProperties["p"].Value); 1505 } 1506 1507 /// <summary> 1508 /// Tests that an invalid registry property expression causes an exception (resulting in a project load error) 1509 /// </summary> 1510 /// <param name="propertyExpression"></param> 1511 private void ConfigFileInvalidRegistryExpressionHelper(string propertyExpression) 1512 { 1513 bool caught = false; 1514 try 1515 { 1516 // this should throw... 1517 ConfigFileValidRegistryExpressionHelper(propertyExpression, String.Empty); 1518 } 1519 catch (InvalidToolsetDefinitionException ex) 1520 { 1521 Console.WriteLine(ex.Message); 1522 caught = true; 1523 } 1524 1525 Assertion.AssertEquals(true, caught); 1526 } 1527 1528 /// <summary> 1529 /// Tests that a specified registry property expression evaluates to specified value 1530 /// </summary> 1531 /// <param name="propertyExpression"></param> 1532 private void ConfigFileValidRegistryExpressionHelper(string propertyExpression, string expectedValue) 1533 { 1534 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1535 <configuration> 1536 <configSections> 1537 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1538 </configSections> 1539 <msbuildToolsets default=""2.0""> 1540 <toolset toolsVersion=""2.0""> 1541 <property name=""MSBuildBinPath"" value=""xxxx""/> 1542 " + propertyExpression + @" 1543 </toolset> 1544 </msbuildToolsets> 1545 </configuration>"); 1546 1547 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1548 1549 1550 ToolsetReader.ReadAllToolsets 1551 ( 1552 values, 1553 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1554 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1555 new BuildPropertyGroup(), 1556 new BuildPropertyGroup(), 1557 ToolsetDefinitionLocations.ConfigurationFile 1558 ); 1559 1560 Assertion.AssertEquals(1, values.Count); 1561 Assertion.AssertEquals(expectedValue, values["2.0"].BuildProperties["p"].Value); 1562 } 1563 1564 /// <summary> 1565 /// Tests the case where application configuration file overrides a value already specified in the registry 1566 /// </summary> 1567 [Test] 1568 public void GetToolsetData_ConflictingPropertyValuesSameCase() 1569 { 1570 // Registry Read 1571 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1572 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 1573 1574 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1575 <configuration> 1576 <configSections> 1577 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1578 </configSections> 1579 <msbuildToolsets default=""2.0""> 1580 <toolset toolsVersion=""2.0""> 1581 <property name=""MSBuildBinPath"" value=""D:\somedifferentpath""/> 1582 </toolset> 1583 </msbuildToolsets> 1584 </configuration>"); 1585 1586 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1587 1588 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1589 ( 1590 values, 1591 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1592 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1593 new BuildPropertyGroup(), 1594 new BuildPropertyGroup(), 1595 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1596 ); 1597 1598 Assertion.AssertEquals(1, values.Count); 1599 Assertion.AssertEquals(0, values["2.0"].BuildProperties.Count); 1600 Assertion.AssertEquals(@"D:\somedifferentpath", values["2.0"].ToolsPath); 1601 } 1602 1603 /// <summary> 1604 /// Tests when properties are defined in the registry as 1605 /// well as in the config file for the same tools version. 1606 /// We should not merge them; we should take the config file ones only 1607 /// </summary> 1608 [Test] 1609 public void GetToolsetData_NoMerging() 1610 { 1611 // Registry Read 1612 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1613 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 1614 key1.SetValue("SomeRegistryProperty", @"SomeRegistryValue"); 1615 1616 // Set the config file contents as needed 1617 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1618 <configuration> 1619 <configSections> 1620 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1621 </configSections> 1622 <msbuildToolsets default=""2.0""> 1623 <toolset toolsVersion=""2.0""> 1624 <property name=""MSBuildBinPath"" value=""D:\someotherpath""/> 1625 <property name=""SomeConfigProperty"" value=""SomeConfigValue""/> 1626 </toolset> 1627 </msbuildToolsets> 1628 </configuration>"); 1629 1630 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1631 1632 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1633 ( 1634 values, 1635 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1636 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1637 new BuildPropertyGroup(), 1638 new BuildPropertyGroup(), 1639 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1640 ); 1641 1642 Assertion.AssertEquals(1, values.Count); 1643 Assertion.AssertEquals(1, values["2.0"].BuildProperties.Count); 1644 Assertion.AssertEquals(@"D:\someotherpath", values["2.0"].ToolsPath); 1645 Assertion.AssertEquals(null, values["2.0"].BuildProperties["SomeRegistryProperty"]); // Was zapped 1646 Assertion.AssertEquals(@"SomeConfigValue", values["2.0"].BuildProperties["SomeConfigProperty"].Value); 1647 } 1648 1649 /// <summary> 1650 /// The absence of the ToolsVersion attribute on the main Project element in a project file means 1651 /// that the engine's default tools version should be used. 1652 /// </summary> 1653 [Test] 1654 public void ToolsVersionAttributeNotSpecifiedOnProjectElementAndDefaultVersionSpecifiedInRegistry() 1655 { 1656 Engine e = new Engine(); 1657 e.AddToolset(new Toolset("2.0", "20toolsPath")); 1658 e.AddToolset(new Toolset("4.0", "40toolsPath")); 1659 1660 string projectPath = ObjectModelHelpers.CreateFileInTempProjectDirectory("x.proj", @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" />"); 1661 1662 Project project = e.CreateNewProject(); 1663 project.Load(projectPath); 1664 1665 Assertion.AssertEquals("2.0", project.ToolsVersion); 1666 Assertion.AssertEquals("2.0", project.DefaultToolsVersion); 1667 } 1668 1669 /// <summary> 1670 /// Tests the case when no values are specified in the registry 1671 /// </summary> 1672 [Test] GetToolsetData_RegistryNotPresent()1673 public void GetToolsetData_RegistryNotPresent() 1674 { 1675 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1676 <configuration> 1677 <configSections> 1678 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1679 </configSections> 1680 <msbuildToolsets default=""2.0""> 1681 <toolset toolsVersion=""2.0""> 1682 <property name=""MSBUILDBINPATH"" value=""D:\somedifferentpath""/> 1683 </toolset> 1684 </msbuildToolsets> 1685 </configuration>"); 1686 1687 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1688 1689 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1690 ( 1691 values, 1692 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1693 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1694 new BuildPropertyGroup(), 1695 new BuildPropertyGroup(), 1696 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1697 ); 1698 1699 Assertion.AssertEquals(1, values.Count); 1700 Assertion.AssertEquals(0, values["2.0"].BuildProperties.Count); 1701 Assertion.AssertEquals(@"D:\somedifferentpath", values["2.0"].ToolsPath); 1702 } 1703 1704 /// <summary> 1705 /// Test the case where nothing is specified in the config file 1706 /// Note that config file not present is same as config file 1707 /// with no MSBuildToolsets Section 1708 /// </summary> 1709 [Test] GetToolsetData_ConfigFileNotPresent()1710 public void GetToolsetData_ConfigFileNotPresent() 1711 { 1712 // Registry Read 1713 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1714 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 1715 1716 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1717 1718 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1719 ( 1720 values, 1721 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1722 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1723 new BuildPropertyGroup(), 1724 new BuildPropertyGroup(), 1725 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1726 ); 1727 1728 Assertion.AssertEquals(1, values.Count); 1729 Assertion.AssertEquals(0, values["2.0"].BuildProperties.Count); 1730 Assertion.AssertEquals(@"D:\somepath", values["2.0"].ToolsPath); 1731 } 1732 1733 /// <summary> 1734 /// Tests the case where nothing is specified in registry and config file 1735 /// </summary> 1736 [Test] GetToolsetData_RegistryAndConfigNotPresent()1737 public void GetToolsetData_RegistryAndConfigNotPresent() 1738 { 1739 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1740 1741 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1742 ( 1743 values, 1744 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1745 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1746 new BuildPropertyGroup(), 1747 new BuildPropertyGroup(), 1748 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1749 ); 1750 1751 Assertion.AssertEquals(1 /* fallback */, values.Count); 1752 } 1753 1754 /// <summary> 1755 /// Tests the case when reading config file throws an exception 1756 /// </summary> 1757 [Test] 1758 [ExpectedException(typeof(InvalidToolsetDefinitionException))] GetToolsetData_ReadConfigThrowsException()1759 public void GetToolsetData_ReadConfigThrowsException() 1760 { 1761 // Registry Read 1762 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1763 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 1764 1765 // Set the config helper to throw exception 1766 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@"", new ConfigurationException()); 1767 1768 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1769 1770 ToolsetReader.ReadAllToolsets 1771 ( 1772 values, 1773 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1774 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1775 new BuildPropertyGroup(), 1776 new BuildPropertyGroup(), 1777 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1778 ); 1779 } 1780 1781 /// <summary> 1782 /// Tests the case where reading from registry throws exception 1783 /// </summary> 1784 [Test] 1785 [ExpectedException(typeof(InvalidToolsetDefinitionException))] GetToolsetData_ReadRegistryOpenSubKeyThrowsException()1786 public void GetToolsetData_ReadRegistryOpenSubKeyThrowsException() 1787 { 1788 RegistryKeyWrapper mockRegistryKey = 1789 new MockRegistryKey(testRegistryPath, MockRegistryKey.WhereToThrow.OpenSubKey); 1790 1791 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1792 <configuration> 1793 <configSections> 1794 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1795 </configSections> 1796 <msbuildToolsets default=""2.0""> 1797 <toolset toolsVersion=""2.0""> 1798 <property name=""MSBuildBinPath"" value=""D:\somedifferentpath""/> 1799 </toolset> 1800 </msbuildToolsets> 1801 </configuration>"); 1802 1803 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1804 1805 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1806 ( 1807 values, 1808 new ToolsetRegistryReader(mockRegistryKey), 1809 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1810 new BuildPropertyGroup(), 1811 new BuildPropertyGroup(), 1812 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1813 ); 1814 } 1815 1816 #endregion 1817 1818 #region "SetDefaultToolsetVersion tests" 1819 1820 /// <summary> 1821 /// Tests that the default ToolsVersion is correctly resolved when specified 1822 /// in registry and config file 1823 /// </summary> 1824 [Test] SetDefaultToolsetVersion_SpecifiedInRegistryAndConfigFile()1825 public void SetDefaultToolsetVersion_SpecifiedInRegistryAndConfigFile() 1826 { 1827 // Set up registry with two tools versions and one property each 1828 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "2.0"); 1829 RegistryKey key1 = toolsVersionsRegistryKey.CreateSubKey("2.0"); 1830 key1.SetValue("MSBuildBinPath", @"D:\somepath"); 1831 RegistryKey key2 = toolsVersionsRegistryKey.CreateSubKey("3.5"); 1832 key2.SetValue("MSBuildBinPath", @"D:\somepath2"); 1833 1834 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1835 <configuration> 1836 <configSections> 1837 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1838 </configSections> 1839 <msbuildToolsets default=""5.0""> 1840 <toolset toolsVersion=""4.0""> 1841 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 1842 </toolset> 1843 <toolset toolsVersion=""5.0""> 1844 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 1845 </toolset> 1846 </msbuildToolsets> 1847 </configuration>"); 1848 1849 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1850 1851 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1852 ( 1853 values, 1854 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1855 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1856 new BuildPropertyGroup(), 1857 new BuildPropertyGroup(), 1858 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1859 ); 1860 1861 Assertion.AssertEquals("5.0", defaultToolsVersion); 1862 } 1863 1864 /// <summary> 1865 /// Tests that the default ToolsVersion is correctly resolved when specified in registry only 1866 /// </summary> 1867 [Test] 1868 public void SetDefaultToolsetVersion_SpecifiedOnlyInRegistry() 1869 { 1870 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1871 <configuration> 1872 <configSections> 1873 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1874 </configSections> 1875 <msbuildToolsets> 1876 <toolset toolsVersion=""3.0""> 1877 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 1878 </toolset> 1879 <toolset toolsVersion=""5.0""> 1880 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 1881 </toolset> 1882 </msbuildToolsets> 1883 </configuration>"); 1884 1885 // Set up registry with two tools versions and one property each 1886 currentVersionRegistryKey.SetValue("DefaultToolsVersion", "3.5"); 1887 RegistryKey key2 = toolsVersionsRegistryKey.CreateSubKey("3.5"); 1888 key2.SetValue("MSBuildBinPath", @"D:\somepath2"); 1889 1890 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1891 1892 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1893 ( 1894 values, 1895 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1896 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1897 new BuildPropertyGroup(), 1898 new BuildPropertyGroup(), 1899 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1900 ); 1901 1902 Assertion.AssertEquals("3.5", defaultToolsVersion); 1903 } 1904 1905 /// <summary> 1906 /// Tests that the default ToolsVersion is correctly resolved 1907 /// when specified in config file only 1908 /// </summary> 1909 [Test] 1910 public void SetDefaultToolsetVersion_SpecifiedOnlyInConfigFile() 1911 { 1912 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1913 <configuration> 1914 <configSections> 1915 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1916 </configSections> 1917 <msbuildToolsets default=""5.0""> 1918 <toolset toolsVersion=""3.5""> 1919 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 1920 </toolset> 1921 <toolset toolsVersion=""5.0""> 1922 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 1923 </toolset> 1924 </msbuildToolsets> 1925 </configuration>"); 1926 1927 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1928 1929 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1930 ( 1931 values, 1932 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1933 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1934 new BuildPropertyGroup(), 1935 new BuildPropertyGroup(), 1936 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1937 ); 1938 1939 1940 Assertion.AssertEquals("5.0", defaultToolsVersion); 1941 } 1942 1943 /// <summary> 1944 /// Tests that the default ToolsVersion is correctly resolved when specified nowhere 1945 /// </summary> 1946 [Test] 1947 public void SetDefaultToolsetVersion_SpecifiedNowhere() 1948 { 1949 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1950 <configuration> 1951 <configSections> 1952 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1953 </configSections> 1954 <msbuildToolsets> 1955 <toolset toolsVersion=""3.5""> 1956 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 1957 </toolset> 1958 <toolset toolsVersion=""5.0""> 1959 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v3.5.x86ret\""/> 1960 </toolset> 1961 </msbuildToolsets> 1962 </configuration>"); 1963 1964 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 1965 1966 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 1967 ( 1968 values, 1969 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 1970 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 1971 new BuildPropertyGroup(), 1972 new BuildPropertyGroup(), 1973 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 1974 ); 1975 1976 string expectedDefault = "2.0"; 1977 if (FrameworkLocationHelper.PathToDotNetFrameworkV20 == null) 1978 { 1979 expectedDefault = "4.0"; 1980 } 1981 1982 Assertion.AssertEquals(expectedDefault, defaultToolsVersion); // built-in default 1983 } 1984 1985 /// <summary> 1986 /// Tests that properties are properly expanded when reading them from the config file 1987 /// </summary> 1988 [Test] 1989 public void PropertiesInToolsetsFromConfigFileAreExpanded() 1990 { 1991 // $(COMPUTERNAME) is just a convenient env var. $(NUMBER_OF_PROCESSORS) isn't defined on Longhorn 1992 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 1993 <configuration> 1994 <configSections> 1995 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 1996 </configSections> 1997 <msbuildToolsets> 1998 <toolset toolsVersion=""3.5""> 1999 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 2000 <property name=""p1"" value=""v1$(p2)""/> 2001 <property name=""p2"" value=""__$(p1)__""/> 2002 <property name=""p3"" value=""$(COMPUTERNAME)""/> 2003 </toolset> 2004 </msbuildToolsets> 2005 </configuration>"); 2006 2007 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 2008 2009 Engine e = new Engine(); 2010 BuildPropertyGroup initialProperties = new BuildPropertyGroup(); 2011 initialProperties.ImportProperties(e.EnvironmentProperties); 2012 initialProperties.ImportProperties(e.GlobalProperties); 2013 2014 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 2015 ( 2016 values, 2017 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 2018 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 2019 new BuildPropertyGroup(), 2020 initialProperties, 2021 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 2022 ); 2023 2024 Assertion.AssertEquals("v1", values["3.5"].BuildProperties["p1"].Value); 2025 // Properties can refer to other properties also defined in the config file 2026 Assertion.AssertEquals("__v1__", values["3.5"].BuildProperties["p2"].Value); 2027 Assertion.AssertEquals(Environment.MachineName, values["3.5"].BuildProperties["p3"].Value); 2028 } 2029 2030 /// <summary> 2031 /// Tests that properties in MSBuildToolsPath are properly expanded when reading them from the config file 2032 /// </summary> 2033 [Test] 2034 public void PropertiesInToolsetsFromConfigFileAreExpandedInToolsPath() 2035 { 2036 // $(COMPUTERNAME) is just a convenient env var. $(NUMBER_OF_PROCESSORS) isn't defined on Longhorn 2037 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 2038 <configuration> 2039 <configSections> 2040 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 2041 </configSections> 2042 <msbuildToolsets> 2043 <toolset toolsVersion=""3.5""> 2044 <property name=""p1"" value=""Microsoft.NET""/> 2045 <property name=""p2"" value=""windows""/> 2046 <property name=""MSBuildBinPath"" value=""D:\windows\$(p1)\Framework\v2.0.x86ret\$(COMPUTERNAME)""/> 2047 <property name=""MSBuildToolsPath"" value=""D:\$(p2)\$(p1)\Framework\v2.0.x86ret\$(COMPUTERNAME)""/> 2048 <property name=""p3"" value=""v3$(MSBuildToolsPath)""/> 2049 </toolset> 2050 </msbuildToolsets> 2051 </configuration>"); 2052 2053 ToolsetCollection values = new ToolsetCollection(new Engine(ToolsetDefinitionLocations.None)); 2054 2055 Engine e = new Engine(); 2056 BuildPropertyGroup initialProperties = new BuildPropertyGroup(); 2057 initialProperties.ImportProperties(e.EnvironmentProperties); 2058 initialProperties.ImportProperties(e.GlobalProperties); 2059 2060 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 2061 ( 2062 values, 2063 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 2064 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 2065 new BuildPropertyGroup(), 2066 initialProperties, 2067 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 2068 ); 2069 2070 Assertion.AssertEquals("Microsoft.NET", values["3.5"].BuildProperties["p1"].Value); 2071 Assertion.AssertEquals("windows", values["3.5"].BuildProperties["p2"].Value); 2072 string expectedToolsPath = @"D:\windows\Microsoft.NET\Framework\v2.0.x86ret\" + Environment.MachineName; 2073 Assertion.AssertEquals(expectedToolsPath, values["3.5"].ToolsPath); 2074 Assertion.AssertEquals("v3" + expectedToolsPath, values["3.5"].BuildProperties["p3"].Value); 2075 } 2076 2077 /// <summary> 2078 /// Global properties are available, but they cannot be overwritten by other toolset properties, just as they cannot 2079 /// be overwritten by project file properties. 2080 /// </summary> 2081 [Test] 2082 public void GlobalPropertiesInToolsetsAreExpandedButAreNotOverwritten() 2083 { 2084 ToolsetConfigurationReaderTestHelper.WriteConfigFile(@" 2085 <configuration> 2086 <configSections> 2087 <section name=""msbuildToolsets"" type=""Microsoft.Build.BuildEngine.ToolsetConfigurationSection, Microsoft.Build.Engine"" /> 2088 </configSections> 2089 <msbuildToolsets> 2090 <toolset toolsVersion=""3.5""> 2091 <property name=""MSBuildBinPath"" value=""D:\windows\Microsoft.NET\Framework\v2.0.x86ret\""/> 2092 <property name=""p1"" value=""$(gp1)""/> 2093 <property name=""gp1"" value=""v2""/> 2094 <property name=""p2"" value=""$(gp1)""/> 2095 </toolset> 2096 </msbuildToolsets> 2097 </configuration>"); 2098 2099 Engine e = new Engine(ToolsetDefinitionLocations.None); 2100 ToolsetCollection values = new ToolsetCollection(e); 2101 2102 BuildPropertyGroup globalProperties = e.GlobalProperties; 2103 globalProperties.SetProperty("gp1", "gv1"); 2104 2105 BuildPropertyGroup initialProperties = new BuildPropertyGroup(); 2106 initialProperties.ImportProperties(e.EnvironmentProperties); 2107 initialProperties.ImportProperties(globalProperties); 2108 2109 string defaultToolsVersion = ToolsetReader.ReadAllToolsets 2110 ( 2111 values, 2112 new ToolsetRegistryReader(new MockRegistryKey(testRegistryPath)), 2113 new ToolsetConfigurationReader(new ReadApplicationConfiguration(ToolsetConfigurationReaderTestHelper.ReadApplicationConfigurationTest)), 2114 globalProperties, 2115 initialProperties, 2116 ToolsetDefinitionLocations.ConfigurationFile | ToolsetDefinitionLocations.Registry 2117 ); 2118 2119 Assertion.AssertEquals("gv1", values["3.5"].BuildProperties["p1"].Value); 2120 Assertion.AssertEquals("gv1", values["3.5"].BuildProperties["p2"].Value); 2121 } 2122 2123 2124 #endregion 2125 } 2126 2127 internal class MockRegistryKey : RegistryKeyWrapper 2128 { 2129 public enum WhereToThrow 2130 { 2131 None, 2132 Name, 2133 GetValue, 2134 GetValueNames, 2135 GetSubKeyNames, 2136 OpenSubKey 2137 } 2138 2139 private WhereToThrow whereToThrow = WhereToThrow.None; 2140 private string subKeyThatDoesNotExist = null; 2141 2142 /// <summary> 2143 /// Construct the mock key with a specified key 2144 /// </summary> 2145 /// <param name="path"></param> 2146 protected MockRegistryKey(RegistryKey wrappedKey, RegistryKey registryHive) 2147 : base(wrappedKey, registryHive) 2148 { } 2149 2150 /// <summary> 2151 /// Construct the mock key with a wrapper 2152 /// </summary> 2153 /// <param name="path"></param> 2154 public MockRegistryKey(string path) 2155 : base(path, Registry.CurrentUser) 2156 { } 2157 2158 /// <summary> 2159 /// Construct the mock key with a wrapper and a designated method 2160 /// to throw from 2161 /// </summary> 2162 /// <param name="path"></param> 2163 /// <param name="whereToThrow"></param> 2164 public MockRegistryKey(string path, WhereToThrow whereToThrow) 2165 : base(path, Registry.CurrentUser) 2166 { 2167 this.whereToThrow = whereToThrow; 2168 } 2169 2170 /// <summary> 2171 /// Construct the mock key with a wrapper and a designated subkey 2172 /// to refuse to open 2173 /// </summary> 2174 /// <param name="path"></param> 2175 /// <param name="whereToThrow"></param> 2176 public MockRegistryKey(string path, string subKeyThatDoesNotExist) 2177 : base(path, Registry.CurrentUser) 2178 { 2179 this.subKeyThatDoesNotExist = subKeyThatDoesNotExist; 2180 } 2181 2182 /// <summary> 2183 /// Name of the registry key 2184 /// </summary> 2185 public override string Name 2186 { 2187 get 2188 { 2189 if (whereToThrow == WhereToThrow.Name) 2190 { 2191 throw new RegistryException("registryException", "registry"); 2192 } 2193 return base.Name; 2194 } 2195 } 2196 2197 /// <summary> 2198 /// Gets the value with name "name" stored under this registry key 2199 /// </summary> 2200 public override object GetValue(string name) 2201 { 2202 if (whereToThrow == WhereToThrow.GetValue) 2203 { 2204 throw new RegistryException("registryException", "registry"); 2205 } 2206 return base.GetValue(name); 2207 } 2208 2209 /// <summary> 2210 /// Gets the names of all values underneath this registry key 2211 /// </summary> 2212 public override string[] GetValueNames() 2213 { 2214 if (whereToThrow == WhereToThrow.GetValueNames) 2215 { 2216 throw new RegistryException("registryException", "registry"); 2217 } 2218 return base.GetValueNames(); 2219 } 2220 2221 /// <summary> 2222 /// Gets the names of all sub keys immediately below this registry key 2223 /// </summary> 2224 /// <returns></returns> 2225 public override string[] GetSubKeyNames() 2226 { 2227 if (whereToThrow == WhereToThrow.GetSubKeyNames) 2228 { 2229 throw new RegistryException("registryException", "registry"); 2230 } 2231 return base.GetSubKeyNames(); 2232 } 2233 2234 /// <summary> 2235 /// Returns the sub key with name "name" as a read only key 2236 /// </summary> 2237 public override RegistryKeyWrapper OpenSubKey(string name) 2238 { 2239 if (whereToThrow == WhereToThrow.OpenSubKey) 2240 { 2241 throw new RegistryException("registryException", "registry"); 2242 } 2243 2244 if (subKeyThatDoesNotExist == name) 2245 { 2246 // Return wrapper around null key 2247 return new MockRegistryKey((RegistryKey)null, Registry.LocalMachine); 2248 } 2249 2250 return base.OpenSubKey(name); 2251 } 2252 2253 } 2254 } 2255 2256