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