1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.IO; 5 using Microsoft.Build.Framework; 6 using Microsoft.Build.Shared; 7 using Microsoft.Build.Tasks; 8 using Microsoft.Build.Utilities; 9 using Xunit; 10 using SystemProcessorArchitecture = System.Reflection.ProcessorArchitecture; 11 12 namespace Microsoft.Build.UnitTests.ResolveAssemblyReference_Tests 13 { 14 /// <summary> 15 /// Unit tests for the ResolveAssemblyReference GlobalAssemblyCache. 16 /// </summary> 17 public sealed class GlobalAssemblyCacheTests : ResolveAssemblyReferenceTestFixture 18 { 19 private const string system4 = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; 20 private const string system2 = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; 21 private const string system1 = "System, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; 22 private const string systemNotStrong = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"; 23 24 private const string system4Path = "c:\\clr4\\System.dll"; 25 private const string system2Path = "c:\\clr2\\System.dll"; 26 private const string system1Path = "c:\\clr2\\System1.dll"; 27 28 private GetAssemblyRuntimeVersion _runtimeVersion = new GetAssemblyRuntimeVersion(MockGetRuntimeVersion); 29 private GetPathFromFusionName _getPathFromFusionName = new GetPathFromFusionName(MockGetPathFromFusionName); 30 private GetGacEnumerator _gacEnumerator = new GetGacEnumerator(MockAssemblyCacheEnumerator); 31 32 /// <summary> 33 /// Verify when the GAC enumerator returns 34 /// 35 /// System, Version=4.0.0.0 Runtime=4.0xxxx 36 /// System, Version=2.0.0.0 Runtime=2.0xxxx 37 /// System, Version=1.0.0.0 Runtime=2.0xxxx 38 /// 39 /// And we target 2.0 runtime that we get the Version 2.0.0.0 system. 40 /// 41 /// This test two aspects. First that we get the correct runtime, second that we get the highest version for that assembly in the runtime. 42 /// </summary> 43 [Fact] VerifySimpleNamev2057020()44 public void VerifySimpleNamev2057020() 45 { 46 // We want to pass a very generic name to get the correct gac entries. 47 AssemblyNameExtension fusionName = new AssemblyNameExtension("System"); 48 49 50 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, _runtimeVersion, new Version("2.0.57027"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, false); 51 Assert.NotNull(path); 52 Assert.True(path.Equals(system2Path, StringComparison.OrdinalIgnoreCase)); 53 } 54 55 56 /// <summary> 57 /// Verify when the GAC enumerator returns 58 /// 59 /// System, Version=4.0.0.0 Runtime=4.0xxxx 60 /// System, Version=2.0.0.0 Runtime=2.0xxxx 61 /// System, Version=1.0.0.0 Runtime=2.0xxxx 62 /// 63 /// And we target 2.0 runtime that we get the Version 2.0.0.0 system. 64 /// 65 /// Verify that by setting the wants specific version to true that we will return the highest version when only the simple name is used. 66 /// Essentially specific version for the gac resolver means do not filter by runtime. 67 /// </summary> 68 [Fact] VerifySimpleNamev2057020SpecificVersion()69 public void VerifySimpleNamev2057020SpecificVersion() 70 { 71 // We want to pass a very generic name to get the correct gac entries. 72 AssemblyNameExtension fusionName = new AssemblyNameExtension("System"); 73 74 75 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, _runtimeVersion, new Version("2.0.0"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, true); 76 Assert.NotNull(path); 77 Assert.True(path.Equals(system4Path, StringComparison.OrdinalIgnoreCase)); 78 } 79 80 /// <summary> 81 /// Verify when the GAC enumerator returns 82 /// 83 /// System, Version=2.0.0.0 Runtime=2.0xxxx 84 /// System, Version=1.0.0.0 Runtime=2.0xxxx 85 /// 86 /// And we target 2.0 runtime that we get the Version 2.0.0.0 system. 87 /// 88 /// Verify that by setting the wants specific version to true that we will return the highest version when only the simple name is used. 89 /// Essentially specific version for the gac resolver means do not filter by runtime. 90 /// </summary> 91 [Fact] VerifyFusionNamev2057020SpecificVersion()92 public void VerifyFusionNamev2057020SpecificVersion() 93 { 94 // We want to pass a very generic name to get the correct gac entries. 95 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, Version=2.0.0.0"); 96 97 98 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, _runtimeVersion, new Version("2.0.0"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, true); 99 Assert.NotNull(path); 100 Assert.True(path.Equals(system2Path, StringComparison.OrdinalIgnoreCase)); 101 } 102 103 /// <summary> 104 /// Verify when the GAC enumerator returns 105 /// 106 /// System, Version=4.0.0.0 Runtime=4.0xxxx 107 /// System, Version=2.0.0.0 Runtime=2.0xxxx 108 /// System, Version=1.0.0.0 Runtime=2.0xxxx 109 /// 110 /// And we target 4.0 runtime that we get the Version 4.0.0.0 system. 111 /// 112 /// This test two aspects. First that we get the correct runtime, second that we get the highest version for that assembly in the runtime. 113 /// </summary> 114 [Fact] VerifySimpleNamev40()115 public void VerifySimpleNamev40() 116 { 117 // We want to pass a very generic name to get the correct gac entries. 118 AssemblyNameExtension fusionName = new AssemblyNameExtension("System"); 119 120 121 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, _runtimeVersion, new Version("4.0.0"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, false); 122 Assert.NotNull(path); 123 Assert.True(path.Equals(system4Path, StringComparison.OrdinalIgnoreCase)); 124 } 125 126 /// <summary> 127 /// Verify when the GAC enumerator returns 128 /// 129 /// System, Version=4.0.0.0 Runtime=4.0xxxx 130 /// System, Version=2.0.0.0 Runtime=2.0xxxx 131 /// System, Version=1.0.0.0 Runtime=2.0xxxx 132 /// 133 /// And we target 4.0 runtime that we get the Version 4.0.0.0 system. 134 /// 135 /// Verify that by setting the wants specific version to true that we will return the highest version when only the simple name is used. 136 /// Essentially specific version for the gac resolver means do not filter by runtime. 137 /// </summary> 138 [Fact] VerifySimpleNamev40SpecificVersion()139 public void VerifySimpleNamev40SpecificVersion() 140 { 141 // We want to pass a very generic name to get the correct gac entries. 142 AssemblyNameExtension fusionName = new AssemblyNameExtension("System"); 143 144 145 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, _runtimeVersion, new Version("4.0.0"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, true); 146 Assert.NotNull(path); 147 Assert.True(path.Equals(system4Path, StringComparison.OrdinalIgnoreCase)); 148 } 149 150 /// <summary> 151 /// Verify when the GAC enumerator returns 152 /// 153 /// System, Version=4.0.0.0 Runtime=4.0xxxx 154 /// 155 /// 156 /// Verify that by setting the wants specific version to true that we will return the highest version when only the simple name is used. 157 /// Essentially specific version for the gac resolver means do not filter by runtime. 158 /// </summary> 159 [Fact] VerifyFusionNamev40SpecificVersion()160 public void VerifyFusionNamev40SpecificVersion() 161 { 162 // We want to pass a very generic name to get the correct gac entries. 163 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, Version=4.0.0.0"); 164 165 166 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, _runtimeVersion, new Version("4.0.0.0"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, true); 167 Assert.NotNull(path); 168 Assert.True(path.Equals(system4Path, StringComparison.OrdinalIgnoreCase)); 169 } 170 171 /// <summary> 172 /// Verify when a assembly name is passed in which has the public key explicitly set to null that we return null as the assembly cannot be in the gac. 173 /// </summary> 174 [Fact] VerifyEmptyPublicKeyspecificVersion()175 public void VerifyEmptyPublicKeyspecificVersion() 176 { 177 Assert.Throws<FileLoadException>(() => 178 { 179 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken="); 180 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, getRuntimeVersion, new Version("2.0.50727"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, true); 181 } 182 ); 183 } 184 185 /// <summary> 186 /// Verify when a assembly name is passed in which has the public key explicitly set to null that we return null as the assembly cannot be in the gac. 187 /// </summary> 188 [Fact] VerifyNullPublicKey()189 public void VerifyNullPublicKey() 190 { 191 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken=null"); 192 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, getRuntimeVersion, new Version("2.0.50727"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, false); 193 Assert.Null(path); 194 } 195 196 /// <summary> 197 /// Verify when a assembly name is passed in which has the public key explicitly set to null that we return null as the assembly cannot be in the gac. 198 /// </summary> 199 [Fact] VerifyNullPublicKeyspecificVersion()200 public void VerifyNullPublicKeyspecificVersion() 201 { 202 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken=null"); 203 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.None, getRuntimeVersion, new Version("2.0.50727"), false, new FileExists(MockFileExists), _getPathFromFusionName, _gacEnumerator, true); 204 Assert.Null(path); 205 } 206 207 208 /// <summary> 209 /// When a processor architecture is on the end of a fusion name we were appending another processor architecture onto the end causing an invalid fusion name 210 /// this was causing the GAC (api's) to crash. 211 /// </summary> 212 [Fact] 213 [Trait("Category", "mono-osx-failing")] VerifyProcessorArchitectureDoesNotCrash()214 public void VerifyProcessorArchitectureDoesNotCrash() 215 { 216 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL"); 217 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.MSIL, getRuntimeVersion, new Version("2.0.50727"), false, new FileExists(MockFileExists), _getPathFromFusionName, null /* use the real gac enumerator*/, false); 218 Assert.Null(path); 219 } 220 221 /// <summary> 222 /// When a processor architecture is on the end of a fusion name we were appending another processor architecture onto the end causing an invalid fusion name 223 /// this was causing the GAC (api's) to crash. 224 /// </summary> 225 [Fact] 226 [Trait("Category", "mono-osx-failing")] VerifyProcessorArchitectureDoesNotCrashSpecificVersion()227 public void VerifyProcessorArchitectureDoesNotCrashSpecificVersion() 228 { 229 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL"); 230 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.MSIL, getRuntimeVersion, new Version("2.0.50727"), false, new FileExists(MockFileExists), _getPathFromFusionName, null /* use the real gac enumerator*/, true); 231 Assert.Null(path); 232 } 233 234 /// <summary> 235 /// See bug 648678, when a processor architecture is on the end of a fusion name we were appending another processor architecture onto the end causing an invalid fusion name 236 /// this was causing the GAC (api's) to crash. 237 /// </summary> 238 [Fact] VerifyProcessorArchitectureDoesNotCrashFullFusionName()239 public void VerifyProcessorArchitectureDoesNotCrashFullFusionName() 240 { 241 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL"); 242 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.MSIL, getRuntimeVersion, new Version("2.0.50727"), true, new FileExists(MockFileExists), _getPathFromFusionName, null /* use the real gac enumerator*/, false); 243 Assert.Null(path); 244 } 245 246 /// <summary> 247 /// When a processor architecture is on the end of a fusion name we were appending another processor architecture onto the end causing an invalid fusion name 248 /// this was causing the GAC (api's) to crash. 249 /// </summary> 250 [Fact] VerifyProcessorArchitectureDoesNotCrashFullFusionNameSpecificVersion()251 public void VerifyProcessorArchitectureDoesNotCrashFullFusionNameSpecificVersion() 252 { 253 AssemblyNameExtension fusionName = new AssemblyNameExtension("System, PublicKeyToken=b77a5c561934e089, ProcessorArchitecture=MSIL"); 254 string path = GlobalAssemblyCache.GetLocation(fusionName, SystemProcessorArchitecture.MSIL, getRuntimeVersion, new Version("2.0.50727"), true, new FileExists(MockFileExists), _getPathFromFusionName, null /* use the real gac enumerator*/, true); 255 Assert.Null(path); 256 } 257 258 259 // System.Runtime dependency calculation tests 260 261 // No dependency 262 [Fact] SystemRuntimeDepends_No_Build()263 public void SystemRuntimeDepends_No_Build() 264 { 265 ResolveAssemblyReference t = new ResolveAssemblyReference(); 266 267 t.BuildEngine = new MockEngine(); 268 269 t.Assemblies = new ITaskItem[] 270 { 271 new TaskItem("Regular"), 272 }; 273 274 t.Assemblies[0].SetMetadata("HintPath", @"C:\SystemRuntime\Regular.dll"); 275 276 t.SearchPaths = DefaultPaths; 277 278 // build mode 279 t.FindDependencies = true; 280 Assert.True( 281 t.Execute 282 ( 283 fileExists, 284 directoryExists, 285 getDirectories, 286 getAssemblyName, 287 getAssemblyMetadata, 288 #if FEATURE_WIN32_REGISTRY 289 getRegistrySubKeyNames, 290 getRegistrySubKeyDefaultValue, 291 #endif 292 getLastWriteTime, 293 getRuntimeVersion, 294 #if FEATURE_WIN32_REGISTRY 295 openBaseKey, 296 #endif 297 checkIfAssemblyIsInGac, 298 isWinMDFile, 299 readMachineTypeFromPEHeader 300 ) 301 ); 302 303 Assert.True(string.Equals(t.DependsOnSystemRuntime, "false", StringComparison.OrdinalIgnoreCase)); // "Expected no System.Runtime dependency found during build." 304 Assert.True(string.Equals(t.DependsOnNETStandard, "false", StringComparison.OrdinalIgnoreCase)); // "Expected no netstandard dependency found during build." 305 306 // intelli build mode 307 t.FindDependencies = false; 308 Assert.True( 309 t.Execute 310 ( 311 fileExists, 312 directoryExists, 313 getDirectories, 314 getAssemblyName, 315 getAssemblyMetadata, 316 #if FEATURE_WIN32_REGISTRY 317 getRegistrySubKeyNames, 318 getRegistrySubKeyDefaultValue, 319 #endif 320 getLastWriteTime, 321 getRuntimeVersion, 322 #if FEATURE_WIN32_REGISTRY 323 openBaseKey, 324 #endif 325 checkIfAssemblyIsInGac, 326 isWinMDFile, 327 readMachineTypeFromPEHeader 328 ) 329 ); 330 331 Assert.True(string.Equals(t.DependsOnSystemRuntime, "false", StringComparison.OrdinalIgnoreCase)); // "Expected no System.Runtime dependency found during intellibuild." 332 Assert.True(string.Equals(t.DependsOnNETStandard, "false", StringComparison.OrdinalIgnoreCase)); // "Expected no netstandard dependency found during intellibuild." 333 } 334 335 336 // Direct dependency 337 [Fact] SystemRuntimeDepends_Yes()338 public void SystemRuntimeDepends_Yes() 339 { 340 ResolveAssemblyReference t = new ResolveAssemblyReference(); 341 342 t.BuildEngine = new MockEngine(); 343 344 t.Assemblies = new ITaskItem[] 345 { 346 new TaskItem("System.Runtime"), 347 }; 348 349 t.Assemblies[0].SetMetadata("HintPath", @"C:\SystemRuntime\System.Runtime.dll"); 350 351 t.SearchPaths = DefaultPaths; 352 353 // build mode 354 t.FindDependencies = true; 355 356 Assert.True( 357 t.Execute 358 ( 359 fileExists, 360 directoryExists, 361 getDirectories, 362 getAssemblyName, 363 getAssemblyMetadata, 364 #if FEATURE_WIN32_REGISTRY 365 getRegistrySubKeyNames, 366 getRegistrySubKeyDefaultValue, 367 #endif 368 getLastWriteTime, 369 getRuntimeVersion, 370 #if FEATURE_WIN32_REGISTRY 371 openBaseKey, 372 #endif 373 checkIfAssemblyIsInGac, 374 isWinMDFile, 375 readMachineTypeFromPEHeader 376 ) 377 ); 378 379 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during build." 380 381 // intelli build mode 382 t.FindDependencies = false; 383 Assert.True( 384 t.Execute 385 ( 386 fileExists, 387 directoryExists, 388 getDirectories, 389 getAssemblyName, 390 getAssemblyMetadata, 391 #if FEATURE_WIN32_REGISTRY 392 getRegistrySubKeyNames, 393 getRegistrySubKeyDefaultValue, 394 #endif 395 getLastWriteTime, 396 getRuntimeVersion, 397 #if FEATURE_WIN32_REGISTRY 398 openBaseKey, 399 #endif 400 checkIfAssemblyIsInGac, 401 isWinMDFile, 402 readMachineTypeFromPEHeader 403 ) 404 ); 405 406 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during intellibuild." 407 } 408 409 // Indirect dependency 410 [Fact] 411 [Trait("Category", "mono-osx-failing")] SystemRuntimeDepends_Yes_Indirect()412 public void SystemRuntimeDepends_Yes_Indirect() 413 { 414 ResolveAssemblyReference t = new ResolveAssemblyReference(); 415 416 t.BuildEngine = new MockEngine(); 417 418 t.Assemblies = new ITaskItem[] 419 { 420 new TaskItem("Portable"), 421 }; 422 423 t.Assemblies[0].SetMetadata("HintPath", @"C:\SystemRuntime\Portable.dll"); 424 425 t.SearchPaths = DefaultPaths; 426 427 // build mode 428 t.FindDependencies = true; 429 430 Assert.True( 431 t.Execute 432 ( 433 fileExists, 434 directoryExists, 435 getDirectories, 436 getAssemblyName, 437 getAssemblyMetadata, 438 #if FEATURE_WIN32_REGISTRY 439 getRegistrySubKeyNames, 440 getRegistrySubKeyDefaultValue, 441 #endif 442 getLastWriteTime, 443 getRuntimeVersion, 444 #if FEATURE_WIN32_REGISTRY 445 openBaseKey, 446 #endif 447 checkIfAssemblyIsInGac, 448 isWinMDFile, 449 readMachineTypeFromPEHeader 450 ) 451 ); 452 453 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during build." 454 455 // intelli build mode 456 t.FindDependencies = false; 457 Assert.True( 458 t.Execute 459 ( 460 fileExists, 461 directoryExists, 462 getDirectories, 463 getAssemblyName, 464 getAssemblyMetadata, 465 #if FEATURE_WIN32_REGISTRY 466 getRegistrySubKeyNames, 467 getRegistrySubKeyDefaultValue, 468 #endif 469 getLastWriteTime, 470 getRuntimeVersion, 471 #if FEATURE_WIN32_REGISTRY 472 openBaseKey, 473 #endif 474 checkIfAssemblyIsInGac, 475 isWinMDFile, 476 readMachineTypeFromPEHeader 477 ) 478 ); 479 480 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during intellibuild." 481 } 482 483 [Fact] SystemRuntimeDepends_Yes_Indirect_ExternallyResolved()484 public void SystemRuntimeDepends_Yes_Indirect_ExternallyResolved() 485 { 486 ResolveAssemblyReference t = new ResolveAssemblyReference(); 487 488 t.BuildEngine = new MockEngine(); 489 490 t.Assemblies = new ITaskItem[] 491 { 492 new TaskItem("Portable"), 493 }; 494 495 t.Assemblies[0].SetMetadata("ExternallyResolved", "true"); 496 t.Assemblies[0].SetMetadata("HintPath", s_portableDllPath); 497 498 t.SearchPaths = DefaultPaths; 499 500 // build mode 501 t.FindDependencies = true; 502 503 Assert.True(t.Execute( 504 fileExists, 505 directoryExists, 506 getDirectories, 507 getAssemblyName, 508 getAssemblyMetadata, 509 #if FEATURE_WIN32_REGISTRY 510 getRegistrySubKeyNames, 511 getRegistrySubKeyDefaultValue, 512 #endif 513 getLastWriteTime, 514 getRuntimeVersion, 515 #if FEATURE_WIN32_REGISTRY 516 openBaseKey, 517 #endif 518 checkIfAssemblyIsInGac, 519 isWinMDFile, 520 readMachineTypeFromPEHeader)); 521 522 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during build." 523 524 // intelli build mode 525 t.FindDependencies = false; 526 Assert.True(t.Execute( 527 fileExists, 528 directoryExists, 529 getDirectories, 530 getAssemblyName, 531 getAssemblyMetadata, 532 #if FEATURE_WIN32_REGISTRY 533 getRegistrySubKeyNames, 534 getRegistrySubKeyDefaultValue, 535 #endif 536 getLastWriteTime, 537 getRuntimeVersion, 538 #if FEATURE_WIN32_REGISTRY 539 openBaseKey, 540 #endif 541 checkIfAssemblyIsInGac, isWinMDFile, 542 readMachineTypeFromPEHeader)); 543 544 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during intellibuild." 545 } 546 547 [Fact] NETStandardDepends_Yes()548 public void NETStandardDepends_Yes() 549 { 550 ResolveAssemblyReference t = new ResolveAssemblyReference(); 551 552 t.BuildEngine = new MockEngine(); 553 554 t.Assemblies = new ITaskItem[] 555 { 556 new TaskItem("netstandard"), 557 }; 558 559 t.Assemblies[0].SetMetadata("HintPath", @"C:\NetStandard\netstandard.dll"); 560 561 t.SearchPaths = DefaultPaths; 562 563 // build mode 564 t.FindDependencies = true; 565 566 Assert.True(t.Execute( 567 fileExists, 568 directoryExists, 569 getDirectories, 570 getAssemblyName, 571 getAssemblyMetadata, 572 #if FEATURE_WIN32_REGISTRY 573 getRegistrySubKeyNames, 574 getRegistrySubKeyDefaultValue, 575 #endif 576 getLastWriteTime, 577 getRuntimeVersion, 578 #if FEATURE_WIN32_REGISTRY 579 openBaseKey, 580 #endif 581 checkIfAssemblyIsInGac, 582 isWinMDFile, 583 readMachineTypeFromPEHeader)); 584 585 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during build." 586 587 // intelli build mode 588 t.FindDependencies = false; 589 Assert.True(t.Execute( 590 fileExists, 591 directoryExists, 592 getDirectories, 593 getAssemblyName, 594 getAssemblyMetadata, 595 #if FEATURE_WIN32_REGISTRY 596 getRegistrySubKeyNames, 597 getRegistrySubKeyDefaultValue, 598 #endif 599 getLastWriteTime, 600 getRuntimeVersion, 601 #if FEATURE_WIN32_REGISTRY 602 openBaseKey, 603 #endif 604 checkIfAssemblyIsInGac, 605 isWinMDFile, 606 readMachineTypeFromPEHeader)); 607 608 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during intellibuild." 609 } 610 611 [Fact] NETStandardDepends_Yes_Indirect()612 public void NETStandardDepends_Yes_Indirect() 613 { 614 ResolveAssemblyReference t = new ResolveAssemblyReference(); 615 616 t.BuildEngine = new MockEngine(); 617 618 t.Assemblies = new ITaskItem[] 619 { 620 new TaskItem("netstandardlibrary"), 621 }; 622 623 t.Assemblies[0].SetMetadata("HintPath", s_netstandardLibraryDllPath); 624 625 t.SearchPaths = DefaultPaths; 626 627 // build mode 628 t.FindDependencies = true; 629 630 Assert.True(t.Execute( 631 fileExists, 632 directoryExists, 633 getDirectories, 634 getAssemblyName, 635 getAssemblyMetadata, 636 #if FEATURE_WIN32_REGISTRY 637 getRegistrySubKeyNames, 638 getRegistrySubKeyDefaultValue, 639 #endif 640 getLastWriteTime, 641 getRuntimeVersion, 642 #if FEATURE_WIN32_REGISTRY 643 openBaseKey, 644 #endif 645 checkIfAssemblyIsInGac, 646 isWinMDFile, 647 readMachineTypeFromPEHeader)); 648 649 Console.WriteLine (((MockEngine)t.BuildEngine).Log); 650 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during build." 651 652 // intelli build mode 653 t.FindDependencies = false; 654 Assert.True(t.Execute( 655 fileExists, 656 directoryExists, 657 getDirectories, 658 getAssemblyName, 659 getAssemblyMetadata, 660 #if FEATURE_WIN32_REGISTRY 661 getRegistrySubKeyNames, 662 getRegistrySubKeyDefaultValue, 663 #endif 664 getLastWriteTime, 665 getRuntimeVersion, 666 #if FEATURE_WIN32_REGISTRY 667 openBaseKey, 668 #endif 669 checkIfAssemblyIsInGac, 670 isWinMDFile, 671 readMachineTypeFromPEHeader)); 672 673 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during intellibuild." 674 } 675 676 677 [Fact] NETStandardDepends_Yes_Indirect_ExternallyResolved()678 public void NETStandardDepends_Yes_Indirect_ExternallyResolved() 679 { 680 ResolveAssemblyReference t = new ResolveAssemblyReference(); 681 682 t.BuildEngine = new MockEngine(); 683 684 t.Assemblies = new ITaskItem[] 685 { 686 new TaskItem("netstandardlibrary"), 687 }; 688 689 t.Assemblies[0].SetMetadata("ExternallyResolved", "true"); 690 t.Assemblies[0].SetMetadata("HintPath", s_netstandardLibraryDllPath); 691 692 t.SearchPaths = DefaultPaths; 693 694 // build mode 695 t.FindDependencies = true; 696 697 Assert.True(t.Execute( 698 fileExists, 699 directoryExists, 700 getDirectories, 701 getAssemblyName, 702 getAssemblyMetadata, 703 #if FEATURE_WIN32_REGISTRY 704 getRegistrySubKeyNames, 705 getRegistrySubKeyDefaultValue, 706 #endif 707 getLastWriteTime, 708 getRuntimeVersion, 709 #if FEATURE_WIN32_REGISTRY 710 openBaseKey, 711 #endif 712 checkIfAssemblyIsInGac, 713 isWinMDFile, 714 readMachineTypeFromPEHeader)); 715 716 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during build." 717 718 // intelli build mode 719 t.FindDependencies = false; 720 Assert.True(t.Execute( 721 fileExists, 722 directoryExists, 723 getDirectories, 724 getAssemblyName, 725 getAssemblyMetadata, 726 #if FEATURE_WIN32_REGISTRY 727 getRegistrySubKeyNames, 728 getRegistrySubKeyDefaultValue, 729 #endif 730 getLastWriteTime, 731 getRuntimeVersion, 732 #if FEATURE_WIN32_REGISTRY 733 openBaseKey, 734 #endif 735 checkIfAssemblyIsInGac, 736 isWinMDFile, 737 readMachineTypeFromPEHeader)); 738 739 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during intellibuild." 740 } 741 742 [Fact] DependsOn_NETStandard_and_SystemRuntime()743 public void DependsOn_NETStandard_and_SystemRuntime() 744 { 745 ResolveAssemblyReference t = new ResolveAssemblyReference(); 746 747 t.BuildEngine = new MockEngine(); 748 749 t.Assemblies = new ITaskItem[] 750 { 751 new TaskItem("netstandardlibrary"), 752 new TaskItem("Portable"), 753 }; 754 755 t.Assemblies[0].SetMetadata("HintPath", s_netstandardLibraryDllPath); 756 t.Assemblies[1].SetMetadata("HintPath", s_portableDllPath); 757 758 t.SearchPaths = DefaultPaths; 759 760 // build mode 761 t.FindDependencies = true; 762 763 Assert.True(t.Execute( 764 fileExists, 765 directoryExists, 766 getDirectories, 767 getAssemblyName, 768 getAssemblyMetadata, 769 #if FEATURE_WIN32_REGISTRY 770 getRegistrySubKeyNames, 771 getRegistrySubKeyDefaultValue, 772 #endif 773 getLastWriteTime, 774 getRuntimeVersion, 775 #if FEATURE_WIN32_REGISTRY 776 openBaseKey, 777 #endif 778 checkIfAssemblyIsInGac, 779 isWinMDFile, 780 readMachineTypeFromPEHeader)); 781 782 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during build." 783 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during build." 784 785 // intelli build mode 786 t.FindDependencies = false; 787 Assert.True(t.Execute( 788 fileExists, 789 directoryExists, 790 getDirectories, 791 getAssemblyName, 792 getAssemblyMetadata, 793 #if FEATURE_WIN32_REGISTRY 794 getRegistrySubKeyNames, 795 getRegistrySubKeyDefaultValue, 796 #endif 797 getLastWriteTime, 798 getRuntimeVersion, 799 #if FEATURE_WIN32_REGISTRY 800 openBaseKey, 801 #endif 802 checkIfAssemblyIsInGac, 803 isWinMDFile, 804 readMachineTypeFromPEHeader)); 805 806 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during intellibuild." 807 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during intellibuild." 808 } 809 810 [Fact] DependsOn_NETStandard_and_SystemRuntime_ExternallyResolved()811 public void DependsOn_NETStandard_and_SystemRuntime_ExternallyResolved() 812 { 813 ResolveAssemblyReference t = new ResolveAssemblyReference(); 814 815 t.BuildEngine = new MockEngine(); 816 817 t.Assemblies = new ITaskItem[] 818 { 819 new TaskItem("netstandardlibrary"), 820 new TaskItem("Portable"), 821 }; 822 823 t.Assemblies[0].SetMetadata("ExternallyResolved", "true"); 824 t.Assemblies[0].SetMetadata("HintPath", s_netstandardLibraryDllPath); 825 t.Assemblies[1].SetMetadata("ExternallyResolved", "true"); 826 t.Assemblies[1].SetMetadata("HintPath", s_portableDllPath); 827 828 t.SearchPaths = DefaultPaths; 829 830 // build mode 831 t.FindDependencies = true; 832 833 Assert.True(t.Execute( 834 fileExists, 835 directoryExists, 836 getDirectories, 837 getAssemblyName, 838 getAssemblyMetadata, 839 #if FEATURE_WIN32_REGISTRY 840 getRegistrySubKeyNames, 841 getRegistrySubKeyDefaultValue, 842 #endif 843 getLastWriteTime, 844 getRuntimeVersion, 845 #if FEATURE_WIN32_REGISTRY 846 openBaseKey, 847 #endif 848 checkIfAssemblyIsInGac, 849 isWinMDFile, 850 readMachineTypeFromPEHeader)); 851 852 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during build." 853 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during build." 854 855 // intelli build mode 856 t.FindDependencies = false; 857 Assert.True(t.Execute( 858 fileExists, 859 directoryExists, 860 getDirectories, 861 getAssemblyName, 862 getAssemblyMetadata, 863 #if FEATURE_WIN32_REGISTRY 864 getRegistrySubKeyNames, 865 getRegistrySubKeyDefaultValue, 866 #endif 867 getLastWriteTime, 868 getRuntimeVersion, 869 #if FEATURE_WIN32_REGISTRY 870 openBaseKey, 871 #endif 872 checkIfAssemblyIsInGac, 873 isWinMDFile, 874 readMachineTypeFromPEHeader)); 875 876 Assert.True(string.Equals(t.DependsOnSystemRuntime, "true", StringComparison.OrdinalIgnoreCase)); // "Expected System.Runtime dependency found during intellibuild." 877 Assert.True(string.Equals(t.DependsOnNETStandard, "true", StringComparison.OrdinalIgnoreCase)); // "Expected netstandard dependency found during intellibuild." 878 } 879 880 #region HelperDelegates 881 MockGetRuntimeVersion(string path)882 private static string MockGetRuntimeVersion(string path) 883 { 884 if (path.Equals(system1Path, StringComparison.OrdinalIgnoreCase)) 885 { 886 return "v2.0.50727"; 887 } 888 889 if (path.Equals(system4Path, StringComparison.OrdinalIgnoreCase)) 890 { 891 return "v4.0.0"; 892 } 893 894 if (path.Equals(system2Path, StringComparison.OrdinalIgnoreCase)) 895 { 896 return "v2.0.50727"; 897 } 898 899 return String.Empty; 900 } 901 MockFileExists(string path)902 private bool MockFileExists(string path) 903 { 904 return true; 905 } 906 MockGetPathFromFusionName(string strongName)907 private static string MockGetPathFromFusionName(string strongName) 908 { 909 if (strongName.Equals(system1, StringComparison.OrdinalIgnoreCase)) 910 { 911 return system1Path; 912 } 913 914 if (strongName.Equals(system2, StringComparison.OrdinalIgnoreCase)) 915 { 916 return system2Path; 917 } 918 919 if (strongName.Equals(systemNotStrong, StringComparison.OrdinalIgnoreCase)) 920 { 921 return system2Path; 922 } 923 924 if (strongName.Equals(system4, StringComparison.OrdinalIgnoreCase)) 925 { 926 return system4Path; 927 } 928 929 return String.Empty; 930 } 931 MockAssemblyCacheEnumerator(string strongName)932 private static IEnumerable<AssemblyNameExtension> MockAssemblyCacheEnumerator(string strongName) 933 { 934 List<string> listOfAssemblies = new List<string>(); 935 936 if (strongName.StartsWith("System, Version=2.0.0.0", StringComparison.OrdinalIgnoreCase)) 937 { 938 listOfAssemblies.Add(system2); 939 } 940 else if (strongName.StartsWith("System, Version=4.0.0.0", StringComparison.OrdinalIgnoreCase)) 941 { 942 listOfAssemblies.Add(system4); 943 } 944 else 945 { 946 listOfAssemblies.Add(system1); 947 listOfAssemblies.Add(system2); 948 listOfAssemblies.Add(system4); 949 } 950 return new MockEnumerator(listOfAssemblies); 951 } 952 953 internal class MockEnumerator : IEnumerable<AssemblyNameExtension> 954 { 955 private List<string> _assembliesToEnumerate = null; 956 private List<string>.Enumerator _enumerator; 957 MockEnumerator(List<string> assembliesToEnumerate)958 public MockEnumerator(List<string> assembliesToEnumerate) 959 { 960 _assembliesToEnumerate = assembliesToEnumerate; 961 962 _enumerator = assembliesToEnumerate.GetEnumerator(); 963 } 964 965 GetEnumerator()966 public IEnumerator<AssemblyNameExtension> GetEnumerator() 967 { 968 foreach (string assembly in _assembliesToEnumerate) 969 { 970 yield return new AssemblyNameExtension(assembly); 971 } 972 } 973 IEnumerable.GetEnumerator()974 IEnumerator IEnumerable.GetEnumerator() 975 { 976 return (IEnumerator)GetEnumerator(); 977 } 978 } 979 980 #endregion 981 } 982 } 983