1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using System.Globalization; 7 using System.IO; 8 using System.Reflection; 9 using System.Resources; 10 using System.Runtime.ExceptionServices; 11 using Xunit; 12 13 namespace System.Tests 14 { 15 public class AppDomainTests : RemoteExecutorTestBase 16 { 17 [Fact] CurrentDomain_Not_Null()18 public void CurrentDomain_Not_Null() 19 { 20 Assert.NotNull(AppDomain.CurrentDomain); 21 } 22 23 [Fact] CurrentDomain_Idempotent()24 public void CurrentDomain_Idempotent() 25 { 26 Assert.Equal(AppDomain.CurrentDomain, AppDomain.CurrentDomain); 27 } 28 29 [Fact] BaseDirectory_Same_As_AppContext()30 public void BaseDirectory_Same_As_AppContext() 31 { 32 Assert.Equal(AppDomain.CurrentDomain.BaseDirectory, AppContext.BaseDirectory); 33 } 34 35 [Fact] RelativeSearchPath_Is_Null()36 public void RelativeSearchPath_Is_Null() 37 { 38 Assert.Null(AppDomain.CurrentDomain.RelativeSearchPath); 39 } 40 41 [Fact] UnhandledException_Add_Remove()42 public void UnhandledException_Add_Remove() 43 { 44 RemoteInvoke(() => { 45 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); 46 AppDomain.CurrentDomain.UnhandledException -= new UnhandledExceptionEventHandler(MyHandler); 47 return SuccessExitCode; 48 }).Dispose(); 49 } 50 51 [Fact] UnhandledException_NotCalled_When_Handled()52 public void UnhandledException_NotCalled_When_Handled() 53 { 54 RemoteInvoke(() => { 55 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(NotExpectedToBeCalledHandler); 56 try 57 { 58 throw new Exception(); 59 } 60 catch 61 { 62 } 63 AppDomain.CurrentDomain.UnhandledException -= new UnhandledExceptionEventHandler(NotExpectedToBeCalledHandler); 64 return SuccessExitCode; 65 }).Dispose(); 66 } 67 68 [ActiveIssue(12716)] 69 [PlatformSpecific(~TestPlatforms.OSX)] // Unhandled exception on a separate process causes xunit to crash on osx 70 [Fact] UnhandledException_Called()71 public void UnhandledException_Called() 72 { 73 System.IO.File.Delete("success.txt"); 74 RemoteInvokeOptions options = new RemoteInvokeOptions(); 75 options.CheckExitCode = false; 76 RemoteInvoke(() => 77 { 78 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); 79 throw new Exception("****This Unhandled Exception is Expected****"); 80 #pragma warning disable 0162 81 return SuccessExitCode; 82 #pragma warning restore 0162 83 }, options).Dispose(); 84 85 Assert.True(System.IO.File.Exists("success.txt")); 86 } 87 NotExpectedToBeCalledHandler(object sender, UnhandledExceptionEventArgs args)88 static void NotExpectedToBeCalledHandler(object sender, UnhandledExceptionEventArgs args) 89 { 90 Assert.True(false, "UnhandledException handler not expected to be called"); 91 } 92 MyHandler(object sender, UnhandledExceptionEventArgs args)93 static void MyHandler(object sender, UnhandledExceptionEventArgs args) 94 { 95 File.Create("success.txt"); 96 } 97 98 [Fact] DynamicDirectory_Null()99 public void DynamicDirectory_Null() 100 { 101 Assert.Null(AppDomain.CurrentDomain.DynamicDirectory); 102 } 103 104 [Fact] FriendlyName()105 public void FriendlyName() 106 { 107 string s = AppDomain.CurrentDomain.FriendlyName; 108 Assert.NotNull(s); 109 string expected = Assembly.GetEntryAssembly()?.GetName()?.Name; 110 111 // GetEntryAssembly may be null (i.e. desktop) 112 if (expected == null) 113 expected = Assembly.GetExecutingAssembly().GetName().Name; 114 115 Assert.Equal(expected, s); 116 } 117 118 [Fact] Id()119 public void Id() 120 { 121 // if running directly on some platforms Xunit may be Id = 1 122 RemoteInvoke(() => { 123 Assert.Equal(1, AppDomain.CurrentDomain.Id); 124 return SuccessExitCode; 125 }).Dispose(); 126 } 127 128 [Fact] IsFullyTrusted()129 public void IsFullyTrusted() 130 { 131 Assert.True(AppDomain.CurrentDomain.IsFullyTrusted); 132 } 133 134 [Fact] IsHomogenous()135 public void IsHomogenous() 136 { 137 Assert.True(AppDomain.CurrentDomain.IsHomogenous); 138 } 139 140 [Fact] FirstChanceException_Add_Remove()141 public void FirstChanceException_Add_Remove() 142 { 143 RemoteInvoke(() => { 144 EventHandler<FirstChanceExceptionEventArgs> handler = (sender, e) => 145 { 146 }; 147 AppDomain.CurrentDomain.FirstChanceException += handler; 148 AppDomain.CurrentDomain.FirstChanceException -= handler; 149 return SuccessExitCode; 150 }).Dispose(); 151 } 152 153 [Fact] FirstChanceException_Called()154 public void FirstChanceException_Called() 155 { 156 RemoteInvoke(() => { 157 bool flag = false; 158 EventHandler<FirstChanceExceptionEventArgs> handler = (sender, e) => 159 { 160 Exception ex = e.Exception; 161 if (ex is FirstChanceTestException) 162 { 163 flag = !flag; 164 } 165 }; 166 AppDomain.CurrentDomain.FirstChanceException += handler; 167 try 168 { 169 throw new FirstChanceTestException("testing"); 170 } 171 catch 172 { 173 } 174 AppDomain.CurrentDomain.FirstChanceException -= handler; 175 Assert.True(flag, "FirstChanceHandler not called"); 176 return SuccessExitCode; 177 }).Dispose(); 178 } 179 180 class FirstChanceTestException : Exception 181 { FirstChanceTestException(string message)182 public FirstChanceTestException(string message) : base(message) 183 { } 184 } 185 186 [Fact] ProcessExit_Add_Remove()187 public void ProcessExit_Add_Remove() 188 { 189 RemoteInvoke(() => { 190 EventHandler handler = (sender, e) => 191 { 192 }; 193 AppDomain.CurrentDomain.ProcessExit += handler; 194 AppDomain.CurrentDomain.ProcessExit -= handler; 195 return SuccessExitCode; 196 }).Dispose(); 197 } 198 199 [Fact] 200 [ActiveIssue("https://github.com/dotnet/corefx/issues/21410", TargetFrameworkMonikers.Uap)] ProcessExit_Called()201 public void ProcessExit_Called() 202 { 203 string path = GetTestFilePath(); 204 RemoteInvoke((pathToFile) => 205 { 206 EventHandler handler = (sender, e) => 207 { 208 File.Create(pathToFile); 209 }; 210 211 AppDomain.CurrentDomain.ProcessExit += handler; 212 return SuccessExitCode; 213 }, path).Dispose(); 214 215 Assert.True(File.Exists(path)); 216 } 217 218 [Fact] ApplyPolicy()219 public void ApplyPolicy() 220 { 221 AssertExtensions.Throws<ArgumentNullException>("assemblyName", () => { AppDomain.CurrentDomain.ApplyPolicy(null); }); 222 AssertExtensions.Throws<ArgumentException>(null, () => { AppDomain.CurrentDomain.ApplyPolicy(""); }); 223 string entryAssembly = Assembly.GetEntryAssembly()?.FullName ?? Assembly.GetExecutingAssembly().FullName; 224 Assert.Equal(AppDomain.CurrentDomain.ApplyPolicy(entryAssembly), entryAssembly); 225 } 226 227 [Fact] 228 [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] CreateDomainNonNetfx()229 public void CreateDomainNonNetfx() 230 { 231 AssertExtensions.Throws<ArgumentNullException>("friendlyName", () => { AppDomain.CreateDomain(null); }); 232 Assert.Throws<PlatformNotSupportedException>(() => { AppDomain.CreateDomain("test"); }); 233 } 234 235 [Fact] 236 [SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework)] CreateDomainNetfx()237 public void CreateDomainNetfx() 238 { 239 Assert.Throws<ArgumentNullException>(() => { AppDomain.CreateDomain(null); }); 240 AppDomain.CreateDomain("test"); 241 } 242 243 [Fact] 244 [ActiveIssue(21680, TargetFrameworkMonikers.UapAot)] ExecuteAssemblyByName()245 public void ExecuteAssemblyByName() 246 { 247 RemoteInvoke(() => { 248 string name = "TestApp"; 249 var assembly = Assembly.Load(name); 250 Assert.Equal(5, AppDomain.CurrentDomain.ExecuteAssemblyByName(assembly.FullName)); 251 Assert.Equal(10, AppDomain.CurrentDomain.ExecuteAssemblyByName(assembly.FullName, new string[2] { "2", "3" })); 252 Assert.Throws<FormatException>(() => AppDomain.CurrentDomain.ExecuteAssemblyByName(assembly.FullName, new string[1] { "a" })); 253 AssemblyName assemblyName = assembly.GetName(); 254 assemblyName.CodeBase = null; 255 Assert.Equal(105, AppDomain.CurrentDomain.ExecuteAssemblyByName(assemblyName, new string[3] { "50", "25", "25" })); 256 return SuccessExitCode; 257 }).Dispose(); 258 } 259 260 [Fact] 261 [ActiveIssue("https://github.com/dotnet/corefx/issues/18718", TargetFrameworkMonikers.Uap)] // Need to copy files out of execution directory ExecuteAssembly()262 public void ExecuteAssembly() 263 { 264 CopyTestAssemblies(); 265 266 string name = Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA", "TestAppOutsideOfTPA.exe"); 267 AssertExtensions.Throws<ArgumentNullException>("assemblyFile", () => AppDomain.CurrentDomain.ExecuteAssembly(null)); 268 Assert.Throws<FileNotFoundException>(() => AppDomain.CurrentDomain.ExecuteAssembly("NonExistentFile.exe")); 269 270 Func<int> executeAssembly = () => AppDomain.CurrentDomain.ExecuteAssembly(name, new string[2] { "2", "3" }, null, Configuration.Assemblies.AssemblyHashAlgorithm.SHA1); 271 272 if (PlatformDetection.IsFullFramework) 273 Assert.Equal(10, executeAssembly()); 274 else 275 Assert.Throws<PlatformNotSupportedException>(() => executeAssembly()); 276 277 Assert.Equal(5, AppDomain.CurrentDomain.ExecuteAssembly(name)); 278 Assert.Equal(10, AppDomain.CurrentDomain.ExecuteAssembly(name, new string[2] { "2", "3" })); 279 } 280 281 [Fact] GetData_SetData()282 public void GetData_SetData() 283 { 284 RemoteInvoke(() => { 285 AssertExtensions.Throws<ArgumentNullException>("name", () => { AppDomain.CurrentDomain.SetData(null, null); }); 286 AppDomain.CurrentDomain.SetData("", null); 287 Assert.Null(AppDomain.CurrentDomain.GetData("")); 288 AppDomain.CurrentDomain.SetData("randomkey", 4); 289 Assert.Equal(4, AppDomain.CurrentDomain.GetData("randomkey")); 290 return SuccessExitCode; 291 }).Dispose(); 292 } 293 294 [Fact] SetData_SameKeyMultipleTimes_ReplacesOldValue()295 public void SetData_SameKeyMultipleTimes_ReplacesOldValue() 296 { 297 RemoteInvoke(() => { 298 string key = Guid.NewGuid().ToString("N"); 299 for (int i = 0; i < 3; i++) 300 { 301 AppDomain.CurrentDomain.SetData(key, i.ToString()); 302 Assert.Equal(i.ToString(), AppDomain.CurrentDomain.GetData(key)); 303 } 304 AppDomain.CurrentDomain.SetData(key, null); 305 return SuccessExitCode; 306 }).Dispose(); 307 } 308 309 [Fact] 310 [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Netfx is more permissive and does not throw")] IsCompatibilitySwitchSet()311 public void IsCompatibilitySwitchSet() 312 { 313 Assert.Throws<ArgumentNullException>(() => { AppDomain.CurrentDomain.IsCompatibilitySwitchSet(null); }); 314 AssertExtensions.Throws<ArgumentException>("switchName", () => { AppDomain.CurrentDomain.IsCompatibilitySwitchSet("");}); 315 Assert.Null(AppDomain.CurrentDomain.IsCompatibilitySwitchSet("randomSwitch")); 316 } 317 318 [Fact] IsDefaultAppDomain()319 public void IsDefaultAppDomain() 320 { 321 // Xunit may be default app domain if run directly 322 RemoteInvoke(() => 323 { 324 Assert.True(AppDomain.CurrentDomain.IsDefaultAppDomain()); 325 return SuccessExitCode; 326 }).Dispose(); 327 } 328 329 [Fact] IsFinalizingForUnload()330 public void IsFinalizingForUnload() 331 { 332 Assert.False(AppDomain.CurrentDomain.IsFinalizingForUnload()); 333 } 334 335 [Fact] toString()336 public void toString() 337 { 338 string actual = AppDomain.CurrentDomain.ToString(); 339 340 // NetFx has additional line endings 341 if (PlatformDetection.IsFullFramework) 342 actual = actual.Trim(); 343 344 string expected = "Name:" + AppDomain.CurrentDomain.FriendlyName + Environment.NewLine + "There are no context policies."; 345 Assert.Equal(expected, actual); 346 } 347 348 [Fact] Unload()349 public void Unload() 350 { 351 RemoteInvoke(() => { 352 AssertExtensions.Throws<ArgumentNullException>("domain", () => { AppDomain.Unload(null); }); 353 Assert.Throws<CannotUnloadAppDomainException>(() => { AppDomain.Unload(AppDomain.CurrentDomain); }); 354 return SuccessExitCode; 355 }).Dispose(); 356 } 357 358 [Fact] Load()359 public void Load() 360 { 361 AssemblyName assemblyName = typeof(AppDomainTests).Assembly.GetName(); 362 assemblyName.CodeBase = null; 363 Assert.NotNull(AppDomain.CurrentDomain.Load(assemblyName)); 364 Assert.NotNull(AppDomain.CurrentDomain.Load(typeof(AppDomainTests).Assembly.FullName)); 365 } 366 367 [Fact] 368 [SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "Does not support Assembly.Load(byte[])")] LoadBytes()369 public void LoadBytes() 370 { 371 Assembly assembly = typeof(AppDomainTests).Assembly; 372 byte[] aBytes = System.IO.File.ReadAllBytes(assembly.Location); 373 Assert.NotNull(AppDomain.CurrentDomain.Load(aBytes)); 374 } 375 376 [Fact] ReflectionOnlyGetAssemblies()377 public void ReflectionOnlyGetAssemblies() 378 { 379 Assert.Equal(0, AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().Length); 380 } 381 382 [Fact] MonitoringIsEnabled()383 public void MonitoringIsEnabled() 384 { 385 RemoteInvoke(() => { 386 Assert.False(AppDomain.MonitoringIsEnabled); 387 Assert.Throws<ArgumentException>(() => { AppDomain.MonitoringIsEnabled = false; }); 388 389 if (PlatformDetection.IsFullFramework) 390 { 391 AppDomain.MonitoringIsEnabled = true; 392 Assert.True(AppDomain.MonitoringIsEnabled); 393 } 394 else 395 { 396 Assert.Throws<PlatformNotSupportedException>(() => { AppDomain.MonitoringIsEnabled = true; }); 397 } 398 return SuccessExitCode; 399 }).Dispose(); 400 } 401 402 [Fact] MonitoringSurvivedMemorySize()403 public void MonitoringSurvivedMemorySize() 404 { 405 Assert.Throws<InvalidOperationException>(() => { var t = AppDomain.CurrentDomain.MonitoringSurvivedMemorySize; }); 406 } 407 408 [Fact] MonitoringSurvivedProcessMemorySize()409 public void MonitoringSurvivedProcessMemorySize() 410 { 411 Assert.Throws<InvalidOperationException>(() => { var t = AppDomain.MonitoringSurvivedProcessMemorySize; }); 412 } 413 414 [Fact] MonitoringTotalAllocatedMemorySize()415 public void MonitoringTotalAllocatedMemorySize() 416 { 417 Assert.Throws<InvalidOperationException>(() => { 418 var t = AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize; 419 }); 420 } 421 422 [Fact] MonitoringTotalProcessorTime()423 public void MonitoringTotalProcessorTime() 424 { 425 Assert.Throws<InvalidOperationException>(() => { 426 var t = AppDomain.CurrentDomain.MonitoringTotalProcessorTime; 427 }); 428 } 429 430 #pragma warning disable 618 431 [Fact] 432 [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] GetCurrentThreadId()433 public void GetCurrentThreadId() 434 { 435 Assert.Equal(AppDomain.GetCurrentThreadId(), Environment.CurrentManagedThreadId); 436 } 437 438 [Fact] ShadowCopyFiles()439 public void ShadowCopyFiles() 440 { 441 Assert.False(AppDomain.CurrentDomain.ShadowCopyFiles); 442 } 443 444 [Fact] AppendPrivatePath()445 public void AppendPrivatePath() 446 { 447 RemoteInvoke(() => { 448 AppDomain.CurrentDomain.AppendPrivatePath("test"); 449 return SuccessExitCode; 450 }).Dispose(); 451 } 452 453 [Fact] ClearPrivatePath()454 public void ClearPrivatePath() 455 { 456 RemoteInvoke(() => { 457 AppDomain.CurrentDomain.ClearPrivatePath(); 458 return SuccessExitCode; 459 }).Dispose(); 460 } 461 462 [Fact] ClearShadowCopyPath()463 public void ClearShadowCopyPath() 464 { 465 RemoteInvoke(() => { 466 AppDomain.CurrentDomain.ClearShadowCopyPath(); 467 return SuccessExitCode; 468 }).Dispose(); 469 } 470 471 [Fact] SetCachePath()472 public void SetCachePath() 473 { 474 RemoteInvoke(() => { 475 AppDomain.CurrentDomain.SetCachePath("test"); 476 return SuccessExitCode; 477 }).Dispose(); 478 } 479 480 [Fact] SetShadowCopyFiles()481 public void SetShadowCopyFiles() 482 { 483 RemoteInvoke(() => { 484 AppDomain.CurrentDomain.SetShadowCopyFiles(); 485 return SuccessExitCode; 486 }).Dispose(); 487 } 488 489 [Fact] SetShadowCopyPath()490 public void SetShadowCopyPath() 491 { 492 RemoteInvoke(() => { 493 AppDomain.CurrentDomain.SetShadowCopyPath("test"); 494 return SuccessExitCode; 495 }).Dispose(); 496 } 497 498 #pragma warning restore 618 499 [Fact] 500 [SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "Does not support Assembly.LoadFile")] 501 [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] GetAssemblies()502 public void GetAssemblies() 503 { 504 RemoteInvoke(() => { 505 Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); 506 Assert.NotNull(assemblies); 507 Assert.True(assemblies.Length > 0, "There must be assemblies already loaded in the process"); 508 AppDomain.CurrentDomain.Load(typeof(AppDomainTests).Assembly.GetName().FullName); 509 Assembly[] assemblies1 = AppDomain.CurrentDomain.GetAssemblies(); 510 // Another thread could have loaded an assembly hence not checking for equality 511 Assert.True(assemblies1.Length >= assemblies.Length, "Assembly.Load of an already loaded assembly should not cause another load"); 512 Assembly.LoadFile(typeof(AppDomain).Assembly.Location); 513 Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies(); 514 Assert.True(assemblies2.Length > assemblies.Length, "Assembly.LoadFile should cause an increase in GetAssemblies list"); 515 int ctr = 0; 516 foreach (var a in assemblies2) 517 { 518 // Dynamic assemblies do not support Location property. 519 if (!a.IsDynamic) 520 { 521 if (a.Location == typeof(AppDomain).Assembly.Location) 522 ctr++; 523 } 524 } 525 foreach (var a in assemblies) 526 { 527 if (!a.IsDynamic) 528 { 529 if (a.Location == typeof(AppDomain).Assembly.Location) 530 ctr--; 531 } 532 } 533 Assert.True(ctr > 0, "Assembly.LoadFile should cause file to be loaded again"); 534 return SuccessExitCode; 535 }).Dispose(); 536 } 537 538 [Fact] 539 [SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "Does not support Assembly.LoadFile")] 540 [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] AssemblyLoad()541 public void AssemblyLoad() 542 { 543 RemoteInvoke(() => { 544 bool AssemblyLoadFlag = false; 545 AssemblyLoadEventHandler handler = (sender, args) => 546 { 547 if (args.LoadedAssembly.FullName.Equals(typeof(AppDomainTests).Assembly.FullName)) 548 { 549 AssemblyLoadFlag = !AssemblyLoadFlag; 550 } 551 }; 552 553 AppDomain.CurrentDomain.AssemblyLoad += handler; 554 555 try 556 { 557 Assembly.LoadFile(typeof(AppDomainTests).Assembly.Location); 558 } 559 finally 560 { 561 AppDomain.CurrentDomain.AssemblyLoad -= handler; 562 } 563 Assert.True(AssemblyLoadFlag); 564 return SuccessExitCode; 565 }).Dispose(); 566 } 567 568 [Fact] 569 [ActiveIssue("https://github.com/dotnet/corefx/issues/18718", TargetFrameworkMonikers.Uap)] // Need to copy files out of execution directory' AssemblyResolve()570 public void AssemblyResolve() 571 { 572 CopyTestAssemblies(); 573 574 RemoteInvoke(() => { 575 ResolveEventHandler handler = (sender, e) => 576 { 577 return Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "AssemblyResolveTests", "AssemblyResolveTests.dll")); 578 }; 579 580 AppDomain.CurrentDomain.AssemblyResolve += handler; 581 582 Type t = Type.GetType("AssemblyResolveTests.Class1, AssemblyResolveTests", true); 583 Assert.NotNull(t); 584 return SuccessExitCode; 585 }).Dispose(); 586 } 587 588 [Fact] 589 [ActiveIssue("https://github.com/dotnet/corefx/issues/18718", TargetFrameworkMonikers.Uap)] // Need to copy files out of execution directory AssemblyResolve_RequestingAssembly()590 public void AssemblyResolve_RequestingAssembly() 591 { 592 CopyTestAssemblies(); 593 594 RemoteInvoke(() => { 595 Assembly a = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA", "TestAppOutsideOfTPA.exe")); 596 597 ResolveEventHandler handler = (sender, e) => 598 { 599 Assert.Equal(e.RequestingAssembly, a); 600 return Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "AssemblyResolveTests", "AssemblyResolveTests.dll")); 601 }; 602 603 AppDomain.CurrentDomain.AssemblyResolve += handler; 604 Type ptype = a.GetType("Program"); 605 MethodInfo myMethodInfo = ptype.GetMethod("foo"); 606 object ret = myMethodInfo.Invoke(null, null); 607 Assert.NotNull(ret); 608 return SuccessExitCode; 609 }).Dispose(); 610 } 611 612 [Fact] AssemblyResolve_IsNotCalledForCoreLibResources()613 public void AssemblyResolve_IsNotCalledForCoreLibResources() 614 { 615 RemoteInvoke(() => 616 { 617 bool assemblyResolveHandlerCalled = false; 618 AppDomain.CurrentDomain.AssemblyResolve += 619 (sender, e) => 620 { 621 // This implementation violates the contract. AssemblyResolve event handler is supposed to return an assembly 622 // that matches the requested identity and that is not the case here. 623 assemblyResolveHandlerCalled = true; 624 return typeof(AppDomainTests).Assembly; 625 }; 626 627 CultureInfo previousUICulture = CultureInfo.CurrentUICulture; 628 CultureInfo.CurrentUICulture = new CultureInfo("de-CH"); 629 try 630 { 631 // The resource lookup for NullReferenceException (generally for CoreLib resources) should not raise the 632 // AssemblyResolve event because a misbehaving handler could cause an infinite recursion check and fail-fast to 633 // be triggered when the resource is not found, as the issue would repeat when reporting that error. 634 Assert.Throws<NullReferenceException>(() => ((string)null).Contains("a")); 635 Assert.False(assemblyResolveHandlerCalled); 636 } 637 finally 638 { 639 CultureInfo.CurrentUICulture = previousUICulture; 640 } 641 642 return SuccessExitCode; 643 }).Dispose(); 644 } 645 646 [Fact] 647 [ActiveIssue(21680, TargetFrameworkMonikers.UapAot)] TypeResolve()648 public void TypeResolve() 649 { 650 RemoteInvoke(() => { 651 Assert.Throws<TypeLoadException>(() => Type.GetType("Program", true)); 652 653 ResolveEventHandler handler = (sender, args) => 654 { 655 return Assembly.Load("TestApp"); 656 }; 657 658 AppDomain.CurrentDomain.TypeResolve += handler; 659 660 Type t; 661 try 662 { 663 t = Type.GetType("Program", true); 664 } 665 finally 666 { 667 AppDomain.CurrentDomain.TypeResolve -= handler; 668 } 669 Assert.NotNull(t); 670 return SuccessExitCode; 671 }).Dispose(); 672 } 673 674 [Fact] 675 [ActiveIssue(21680, TargetFrameworkMonikers.UapAot)] 676 [SkipOnTargetFramework(TargetFrameworkMonikers.UapNotUapAot, "In UWP the resources always exist in the resources.pri file even if the assembly is not loaded")] ResourceResolve()677 public void ResourceResolve() 678 { 679 RemoteInvoke(() => { 680 ResourceManager res = new ResourceManager(typeof(FxResources.TestApp.SR)); 681 Assert.Throws<MissingManifestResourceException>(() => res.GetString("Message")); 682 683 ResolveEventHandler handler = (sender, args) => 684 { 685 return Assembly.Load("TestApp"); 686 }; 687 688 AppDomain.CurrentDomain.ResourceResolve += handler; 689 690 String s; 691 try 692 { 693 s = res.GetString("Message"); 694 } 695 finally 696 { 697 AppDomain.CurrentDomain.ResourceResolve -= handler; 698 } 699 Assert.Equal(s, "Happy Halloween"); 700 return SuccessExitCode; 701 }).Dispose(); 702 } 703 704 [Fact] SetThreadPrincipal()705 public void SetThreadPrincipal() 706 { 707 RemoteInvoke(() => { 708 Assert.Throws<ArgumentNullException>(() => { AppDomain.CurrentDomain.SetThreadPrincipal(null); }); 709 var identity = new System.Security.Principal.GenericIdentity("NewUser"); 710 var principal = new System.Security.Principal.GenericPrincipal(identity, null); 711 AppDomain.CurrentDomain.SetThreadPrincipal(principal); 712 return SuccessExitCode; 713 }).Dispose(); 714 } 715 CopyTestAssemblies()716 private void CopyTestAssemblies() 717 { 718 string destTestAssemblyPath = Path.Combine(Environment.CurrentDirectory, "AssemblyResolveTests", "AssemblyResolveTests.dll"); 719 if (!File.Exists(destTestAssemblyPath) && File.Exists("AssemblyResolveTests.dll")) 720 { 721 Directory.CreateDirectory(Path.GetDirectoryName(destTestAssemblyPath)); 722 File.Copy("AssemblyResolveTests.dll", destTestAssemblyPath, false); 723 } 724 725 destTestAssemblyPath = Path.Combine(Environment.CurrentDirectory, "TestAppOutsideOfTPA", "TestAppOutsideOfTPA.exe"); 726 if (!File.Exists(destTestAssemblyPath) && File.Exists("TestAppOutsideOfTPA.exe")) 727 { 728 Directory.CreateDirectory(Path.GetDirectoryName(destTestAssemblyPath)); 729 File.Copy("TestAppOutsideOfTPA.exe", destTestAssemblyPath, false); 730 } 731 } 732 } 733 } 734 735 namespace FxResources.TestApp 736 { 737 class SR { } 738 } 739