File: InteractiveSessionReferencesTests.cs
Web Access
Project: src\src\Scripting\CSharpTest.Desktop\Microsoft.CodeAnalysis.CSharp.Scripting.Desktop.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Scripting.Desktop.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
extern alias PortableTestUtils;
 
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.CodeAnalysis.Scripting.Hosting;
using Microsoft.CodeAnalysis.Scripting.Test;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using AssertEx = PortableTestUtils::Roslyn.Test.Utilities.AssertEx;
using TestBase = PortableTestUtils::Roslyn.Test.Utilities.TestBase;
using WorkItemAttribute = PortableTestUtils::Roslyn.Test.Utilities.WorkItemAttribute;
using static Microsoft.CodeAnalysis.Scripting.TestCompilationFactory;
using Microsoft.CodeAnalysis.Scripting.TestUtilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Scripting.Test
{
    public class InteractiveSessionReferencesTests : CSharpScriptTestBase
    {
        private static readonly CSharpCompilationOptions s_signedDll =
           new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, cryptoPublicKey: TestResources.TestKeys.PublicKey_ce65828c82a341f2);
 
        private static readonly CSharpCompilationOptions s_signedDll2 =
            new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, cryptoPublicKey: TestResources.TestKeys.PublicKey_ce65828c82a341f2);
 
        [Fact]
        public async Task CompilationChain_GlobalImportsRebinding()
        {
            var options = ScriptOptions.AddImports("System.Diagnostics");
 
            var s0 = await CSharpScript.RunAsync("", options);
 
            ScriptingTestHelpers.AssertCompilationError(s0, @"Process.GetCurrentProcess()",
                // (2,1): error CS0103: The name 'Process' does not exist in the current context
                Diagnostic(ErrorCode.ERR_NameNotInContext, "Process").WithArguments("Process"));
 
            var s1 = s0.ContinueWithAsync($"#r \"{typeof(Process).Assembly.Location}\"");
            var s2 = s1.ContinueWith("Process.GetCurrentProcess()");
 
            Assert.NotNull(s2.Result);
        }
 
        [Fact]
        public async Task CompilationChain_UsingRebinding_AddReference()
        {
            var s0 = await CSharpScript.RunAsync("using System.Diagnostics;", ScriptOptions);
 
            var newOptions = s0.Script.Options.AddReferences(typeof(Process).Assembly);
 
            var s1 = s0.ContinueWithAsync(@"Process.GetCurrentProcess()", newOptions);
 
            Assert.NotNull(s1.Result);
        }
 
        [Fact]
        public async Task CompilationChain_UsingRebinding_Directive()
        {
            var s0 = await CSharpScript.RunAsync("using System.Diagnostics;", ScriptOptions);
 
            var s1 = s0.ContinueWithAsync($@"
#r ""{typeof(Process).Assembly.Location}""
Process.GetCurrentProcess()");
 
            Assert.NotNull(s1.Result);
        }
 
        //
        // General rule for symbol lookup: 
        //
        // Declaration A in submission S hides declaration B in submission T iff
        // S precedes T, and A and B can't coexist in the same scope.
 
        [Fact]
        public void CompilationChain_SubmissionSlots()
        {
            var s =
                CSharpScript.RunAsync("using System;", ScriptOptions).
                ContinueWith("using static System.Environment;").
                ContinueWith("int x; x = 1;").
                ContinueWith("using static System.Math;").
                ContinueWith("int goo(int a) { return a + 1; } ");
 
#if false
            Assert.True(session.executionState.submissions.Length >= 2, "Expected two submissions");
            session.executionState.submissions.Aggregate(0, (i, sub) => { Assert.Equal(i < 2, sub != null); return i + 1; });
#endif
            ScriptingTestHelpers.AssertCompilationError(s, "Version",
                // (1,1): error CS0229: Ambiguity between 'System.Version' and 'System.Environment.Version'
                Diagnostic(ErrorCode.ERR_AmbigMember, "Version").WithArguments("System.Version", "System.Environment.Version"));
 
            s = s.ContinueWith("new System.Collections.Generic.List<Version>()");
            Assert.IsType<List<Version>>(s.Result.ReturnValue);
 
            s = s.ContinueWith("Environment.Version");
            Assert.Equal(Environment.Version, s.Result.ReturnValue);
 
            s = s.ContinueWith("goo(x)");
            Assert.Equal(2, s.Result.ReturnValue);
 
            s = s.ContinueWith("Sin(0)");
            Assert.Equal(0.0, s.Result.ReturnValue);
        }
 
        [Fact]
        public void SearchPaths1()
        {
            var options = ScriptOptions.WithMetadataResolver(ScriptMetadataResolver.WithSearchPaths(RuntimeEnvironment.GetRuntimeDirectory()));
 
            var result = CSharpScript.EvaluateAsync($@"
#r ""System.Data.dll""
#r ""System""
#r ""{typeof(System.Xml.Serialization.IXmlSerializable).GetTypeInfo().Assembly.Location}""
new System.Data.DataSet()
", options).Result;
 
            Assert.True(result is System.Data.DataSet, "Expected DataSet");
        }
 
        /// <summary>
        /// Default search paths can be removed.
        /// </summary>
        [Fact]
        public void SearchPaths_RemoveDefault()
        {
            // remove default paths:
            var options = ScriptOptions;
 
            var source = @"
#r ""System.Data.dll""
new System.Data.DataSet()
";
 
            ScriptingTestHelpers.AssertCompilationError(() => CSharpScript.EvaluateAsync(source, options),
                // (2,1): error CS0006: Metadata file 'System.Data.dll' could not be found
                // #r "System.Data.dll"
                Diagnostic(ErrorCode.ERR_NoMetadataFile, @"#r ""System.Data.dll""").WithArguments("System.Data.dll"),
                // (3,12): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'System' (are you missing an assembly reference?)
                // new System.Data.DataSet()
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Data").WithArguments("Data", "System"));
        }
 
        /// <summary>
        /// Look at base directory (or directory containing #r) before search paths.
        /// </summary>
        [Fact]
        public async Task SearchPaths_BaseDirectory()
        {
            var options = ScriptOptions.
                WithMetadataResolver(new TestMetadataReferenceResolver(
                    pathResolver: new VirtualizedRelativePathResolver(existingFullPaths: new[] { @"C:\dir\x.dll" }, baseDirectory: @"C:\goo\bar"),
                    files: new Dictionary<string, PortableExecutableReference> { { @"C:\dir\x.dll", (PortableExecutableReference)SystemCoreRef } }));
 
            var script = CSharpScript.Create(@"
#r ""x.dll""
using System.Linq;
 
var x = from a in new[] { 1, 2 ,3 } select a + 1;
", options.WithFilePath(@"C:\dir\a.csx"));
 
            var state = await script.RunAsync().ContinueWith<IEnumerable<int>>("x", options.WithFilePath(null));
 
            AssertEx.Equal(new[] { 2, 3, 4 }, state.ReturnValue);
        }
 
        [Fact]
        public async Task References1()
        {
            var options0 = ScriptOptions.AddReferences(
                typeof(Process).Assembly,
                typeof(System.Linq.Expressions.Expression).Assembly);
 
            var s0 = await CSharpScript.RunAsync<Process>($@"
#r ""{typeof(System.Data.DataSet).Assembly.Location}""
#r ""System""
#r ""{typeof(System.Xml.Serialization.IXmlSerializable).Assembly.Location}""
new System.Data.DataSet();
System.Linq.Expressions.Expression.Constant(123);
System.Diagnostics.Process.GetCurrentProcess()
", options0);
 
            Assert.NotNull(s0.ReturnValue);
 
            var options1 = options0.AddReferences(typeof(System.Xml.XmlDocument).Assembly);
 
            var s1 = await s0.ContinueWithAsync<System.Xml.XmlDocument>(@"
new System.Xml.XmlDocument()
", options1);
 
            Assert.NotNull(s1.ReturnValue);
 
            var options2 = options1.AddReferences("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
 
            var s2 = await s1.ContinueWithAsync(@"
System.Drawing.Color.Coral
", options2);
 
            Assert.NotNull(s2.ReturnValue);
 
            var options3 = options2.AddReferences(typeof(System.Windows.Forms.Form).Assembly.Location);
 
            var s3 = await s2.ContinueWithAsync<System.Windows.Forms.Form>(@"
new System.Windows.Forms.Form()
", options3);
 
            Assert.NotNull(s3.ReturnValue);
        }
 
        [Fact]
        public void References2()
        {
            var options = ScriptOptions.
                WithMetadataResolver(ScriptMetadataResolver.WithSearchPaths(RuntimeEnvironment.GetRuntimeDirectory())).
                AddReferences("System.Core", "System.dll").
                AddReferences(typeof(System.Data.DataSet).Assembly);
 
            var process = CSharpScript.EvaluateAsync<Process>($@"
#r ""{typeof(System.Xml.Serialization.IXmlSerializable).Assembly.Location}""
new System.Data.DataSet();
System.Linq.Expressions.Expression.Constant(123);
System.Diagnostics.Process.GetCurrentProcess()
", options).Result;
 
            Assert.NotNull(process);
        }
 
        private static readonly Lazy<bool> s_isSystemV2AndV4Available = new Lazy<bool>(() =>
        {
            string path;
            return GlobalAssemblyCache.Instance.ResolvePartialName("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", out path) != null &&
                   GlobalAssemblyCache.Instance.ResolvePartialName("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", out path) != null;
        });
 
        [Fact]
        public void References_Versioning_FxUnification1()
        {
            if (!s_isSystemV2AndV4Available.Value)
                return;
 
            var script = CSharpScript.Create($@"
#r ""System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089""
#r ""System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089""
 
System.Diagnostics.Process.GetCurrentProcess()
", ScriptOptions);
            script.GetCompilation().VerifyAssemblyVersionsAndAliases(
                "System, Version=2.0.0.0: <superseded>",
                "System, Version=4.0.0.0",
                "mscorlib, Version=4.0.0.0",
                "System.Configuration, Version=4.0.0.0: <implicit>,global",
                "System.Xml, Version=4.0.0.0: <implicit>,global",
                "System.Data.SqlXml, Version=4.0.0.0: <implicit>,global",
                "System.Security, Version=4.0.0.0: <implicit>,global",
                "System.Core, Version=4.0.0.0: <implicit>,global",
                "System.Numerics, Version=4.0.0.0: <implicit>,global",
                "System.Configuration, Version=2.0.0.0: <superseded>",
                "System.Xml, Version=2.0.0.0: <superseded>",
                "System.Data.SqlXml, Version=2.0.0.0: <superseded>",
                "System.Security, Version=2.0.0.0: <superseded>");
 
            Assert.NotNull(script.RunAsync().Result.ReturnValue);
        }
 
        [Fact]
        public void References_Versioning_FxUnification2()
        {
            if (!s_isSystemV2AndV4Available.Value)
                return;
 
            var script0 = CSharpScript.Create($@"
#r ""System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089""
", ScriptOptions);
            var script1 = script0.ContinueWith($@"
#r ""System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089""
");
            var script2 = script1.ContinueWith(@"
System.Diagnostics.Process.GetCurrentProcess()
");
            script0.GetCompilation().VerifyAssemblyVersionsAndAliases(
                "System, Version=2.0.0.0",
                "mscorlib, Version=4.0.0.0",
                "System.Configuration, Version=2.0.0.0: <implicit>,global",
                "System.Xml, Version=2.0.0.0: <implicit>,global",
                "System.Data.SqlXml, Version=2.0.0.0: <implicit>,global",
                "System.Security, Version=2.0.0.0: <implicit>,global");
 
            // TODO (https://github.com/dotnet/roslyn/issues/6456): 
            // This is not correct. "global" alias should be recursively applied on all 
            // dependencies of System, V4. The problem is in ResolveReferencedAssembly which considers
            // System, V2 equivalent to System, V4 and immediately returns, instead of checking if a better match exists.
            // This is not a problem in csc since it can't have both System, V2 and System, V4 among definitions.
            script1.GetCompilation().VerifyAssemblyVersionsAndAliases(
                "System, Version=4.0.0.0",
                "System, Version=2.0.0.0: <superseded>",
                "mscorlib, Version=4.0.0.0",
                "System.Configuration, Version=2.0.0.0: <superseded>",
                "System.Xml, Version=2.0.0.0: <superseded>",
                "System.Data.SqlXml, Version=2.0.0.0: <superseded>",
                "System.Security, Version=2.0.0.0: <superseded>",
                "System.Configuration, Version=4.0.0.0: <implicit>",
                "System.Xml, Version=4.0.0.0: <implicit>",
                "System.Data.SqlXml, Version=4.0.0.0: <implicit>",
                "System.Security, Version=4.0.0.0: <implicit>",
                "System.Core, Version=4.0.0.0: <implicit>",
                "System.Numerics, Version=4.0.0.0: <implicit>");
 
            // TODO (https://github.com/dotnet/roslyn/issues/6456): 
            // "global" alias should be recursively applied on all 
            script2.GetCompilation().VerifyAssemblyVersionsAndAliases(
                "System, Version=4.0.0.0",
                "System, Version=2.0.0.0: <superseded>",
                "mscorlib, Version=4.0.0.0",
                "System.Configuration, Version=2.0.0.0: <superseded>",
                "System.Xml, Version=2.0.0.0: <superseded>",
                "System.Data.SqlXml, Version=2.0.0.0: <superseded>",
                "System.Security, Version=2.0.0.0: <superseded>",
                "System.Configuration, Version=4.0.0.0: <implicit>",
                "System.Xml, Version=4.0.0.0: <implicit>",
                "System.Data.SqlXml, Version=4.0.0.0: <implicit>",
                "System.Security, Version=4.0.0.0: <implicit>",
                "System.Core, Version=4.0.0.0: <implicit>",
                "System.Numerics, Version=4.0.0.0: <implicit>");
 
            Assert.NotNull(script2.EvaluateAsync().Result);
        }
 
        [Fact]
        public void References_Versioning_StrongNames1()
        {
            var c1 = Temp.CreateFile(extension: ".dll").WriteAllBytes(TestResources.General.C1);
            var c2 = Temp.CreateFile(extension: ".dll").WriteAllBytes(TestResources.General.C2);
 
            var result = CSharpScript.EvaluateAsync($@"
#r ""{c1.Path}""
#r ""{c2.Path}""
 
new C()
", ScriptOptions).Result;
 
            Assert.NotNull(result);
        }
 
        [Fact]
        public void References_Versioning_StrongNames2()
        {
            var c1 = Temp.CreateFile(extension: ".dll").WriteAllBytes(TestResources.General.C1);
            var c2 = Temp.CreateFile(extension: ".dll").WriteAllBytes(TestResources.General.C2);
 
            var result = CSharpScript.Create($@"
#r ""{c1.Path}""
", ScriptOptions).ContinueWith($@"
#r ""{c2.Path}""
").ContinueWith(@"
new C()
").EvaluateAsync().Result;
 
            Assert.NotNull(result);
        }
 
        [Fact]
        public void References_Versioning_WeakNames1()
        {
            var c1 = Temp.CreateFile(extension: ".dll").WriteAllBytes(
                CreateCSharpCompilation(@"[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")] public class C {}", new[] { NetFramework.mscorlib }, assemblyName: "C").EmitToArray());
 
            var c2 = Temp.CreateFile(extension: ".dll").WriteAllBytes(
                CreateCSharpCompilation(@"[assembly: System.Reflection.AssemblyVersion(""2.0.0.0"")] public class C {}", new[] { NetFramework.mscorlib }, assemblyName: "C").EmitToArray());
 
            var result = CSharpScript.EvaluateAsync($@"
#r ""{c1.Path}""
#r ""{c2.Path}""
 
new C()
", ScriptOptions).Result;
 
            Assert.NotNull(result);
        }
 
        [Fact]
        public void References_Versioning_WeakNames2()
        {
            var c1 = Temp.CreateFile(extension: ".dll").WriteAllBytes(
                CreateCSharpCompilation(@"[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")] public class C {}", new[] { NetFramework.mscorlib }, assemblyName: "C").EmitToArray());
 
            var c2 = Temp.CreateFile(extension: ".dll").WriteAllBytes(
                CreateCSharpCompilation(@"[assembly: System.Reflection.AssemblyVersion(""2.0.0.0"")] public class C {}", new[] { NetFramework.mscorlib }, assemblyName: "C").EmitToArray());
 
            var result = CSharpScript.Create($@"
#r ""{c1.Path}""
", ScriptOptions).ContinueWith($@"
#r ""{c2.Path}""
").ContinueWith(@"
new C()
").EvaluateAsync().Result;
 
            Assert.NotNull(result);
        }
 
        [Fact]
        public void References_Versioning_WeakNames3()
        {
            var c1 = Temp.CreateFile(extension: ".dll").WriteAllBytes(
                CreateCSharpCompilation(@"[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")] public class C {}", new[] { NetFramework.mscorlib }, assemblyName: "C").EmitToArray());
 
            var c2 = Temp.CreateFile(extension: ".dll").WriteAllBytes(
                CreateCSharpCompilation(@"[assembly: System.Reflection.AssemblyVersion(""2.0.0.0"")] public class C {}", new[] { NetFramework.mscorlib }, assemblyName: "C").EmitToArray());
 
            var script0 = CSharpScript.Create($@"
#r ""{c1.Path}""
var c1 = new C();
", ScriptOptions);
            script0.GetCompilation().VerifyAssemblyVersionsAndAliases(
            "C, Version=1.0.0.0",
            "mscorlib, Version=4.0.0.0");
 
            var script1 = script0.ContinueWith($@"
#r ""{c2.Path}""
var c2 = new C();
");
            script1.GetCompilation().VerifyAssemblyVersionsAndAliases(
                "C, Version=2.0.0.0",
                "C, Version=1.0.0.0: <superseded>",
                "mscorlib, Version=4.0.0.0");
 
            var script2 = script1.ContinueWith(@"
c1 = c2;
");
            script2.GetCompilation().VerifyAssemblyVersionsAndAliases(
                "C, Version=2.0.0.0",
                "C, Version=1.0.0.0: <superseded>",
                "mscorlib, Version=4.0.0.0");
 
            DiagnosticExtensions.VerifyEmitDiagnostics(script2.GetCompilation(),
                // (2,6): error CS0029: Cannot implicitly convert type 'C [{c2.Path}]' to 'C [{c1.Path}]'
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "c2").WithArguments($"C [{c2.Path}]", $"C [{c1.Path}]"));
        }
 
        [Fact]
        public void AssemblyResolution()
        {
            var s0 = CSharpScript.RunAsync("var x = new { a = 3 }; x", ScriptOptions);
            var s1 = s0.ContinueWith<Type>("System.Type.GetType(x.GetType().AssemblyQualifiedName, true)");
            Assert.Equal(s0.Result.ReturnValue.GetType(), s1.Result.ReturnValue);
        }
 
        [Fact]
        public void ReferenceToInvalidType()
        {
            var badTypeBytes = TestResources.MetadataTests.Invalid.ClassLayout;
            var badTypeRef = MetadataReference.CreateFromImage(badTypeBytes.AsImmutableOrNull());
 
            // TODO: enable this with our AssemblyLoader:
            Assembly handler(object _, ResolveEventArgs args)
            {
                if (args.Name.StartsWith("b,", StringComparison.Ordinal))
                {
                    return Assembly.Load(badTypeBytes);
                }
 
                return null;
            }
 
            AppDomain.CurrentDomain.AssemblyResolve += handler;
            try
            {
                var options = ScriptOptions.AddReferences(badTypeRef);
 
                // we shouldn't throw while compiling:
                var script = CSharpScript.Create("new S1()", options);
                script.Compile();
 
                Assert.Throws<TypeLoadException>(() => script.EvaluateAsync().GetAwaiter().GetResult());
            }
            finally
            {
                AppDomain.CurrentDomain.AssemblyResolve -= handler;
            }
        }
 
        public class C { public int x = 1; }
 
        [Fact]
        public async Task HostObjectBinding_DuplicateReferences()
        {
            var options = ScriptOptions.
                AddReferences(typeof(C).Assembly, typeof(C).Assembly);
 
            var s0 = await CSharpScript.RunAsync<int>("x", options, new C());
            var c0 = s0.Script.GetCompilation();
 
            // includes corlib, host type assembly by default:
            AssertEx.Equal(new[]
            {
                typeof(object).GetTypeInfo().Assembly.Location,
                typeof(C).Assembly.Location,
                typeof(C).Assembly.Location,
                typeof(C).Assembly.Location,
            }, c0.ExternalReferences.SelectAsArray(m => m.Display));
 
            Assert.Equal(1, s0.ReturnValue);
 
            var s1 = await s0.ContinueWithAsync($@"
#r ""{typeof(C).Assembly.Location}""
#r ""{typeof(C).Assembly.Location}""
x            
");
            Assert.Equal(1, s1.ReturnValue);
        }
 
        [Fact]
        public async Task MissingRefrencesAutoResolution()
        {
            var portableLib = CSharpCompilation.Create(
                "PortableLib",
                new[] { SyntaxFactory.ParseSyntaxTree("public class C {}") },
                new[] { SystemRuntimePP7Ref },
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
 
            var portableLibRef = portableLib.ToMetadataReference();
 
            var loader = new InteractiveAssemblyLoader();
            loader.RegisterDependency(Assembly.Load(portableLib.EmitToArray().ToArray()));
 
            var s0 = await CSharpScript.Create("new C()", options: ScriptOptions.AddReferences(portableLibRef), assemblyLoader: loader).RunAsync();
            var c0 = s0.Script.GetCompilation();
 
            // includes corlib, host type assembly by default:
            AssertEx.Equal(new[]
            {
                typeof(object).GetTypeInfo().Assembly.Location,
                "PortableLib"
            }, c0.ExternalReferences.SelectAsArray(m => m.Display));
 
            // System.Runtime, 4.0.0.0 depends on all the assemblies below:
            AssertEx.Equal(new[]
            {
                "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                "PortableLib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
                "System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
                "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                "System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                "System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
                "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                "System.Data.SqlXml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                "System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
                "System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
            }, c0.GetBoundReferenceManager().GetReferencedAssemblies().Select(a => a.Value.Identity.GetDisplayName()));
        }
 
        // https://github.com/dotnet/roslyn/issues/2246
        [Fact]
        public void HostObjectInInMemoryAssembly()
        {
            var lib = CreateCSharpCompilation("public class C { public int X = 1, Y = 2; }", new[] { NetFramework.mscorlib }, "HostLib");
            var libImage = lib.EmitToArray();
            var libRef = MetadataImageReference.CreateFromImage(libImage);
 
            var libAssembly = Assembly.Load(libImage.ToArray());
            var globalsType = libAssembly.GetType("C");
            var globals = Activator.CreateInstance(globalsType);
 
            using (var loader = new InteractiveAssemblyLoader())
            {
                loader.RegisterDependency(libAssembly);
 
                var script = CSharpScript.Create<int>(
                    "X+Y",
                    ScriptOptions.WithReferences(libRef),
                    globalsType: globalsType,
                    assemblyLoader: loader);
 
                int result = script.RunAsync(globals).Result.ReturnValue;
                Assert.Equal(3, result);
            }
        }
 
        [Fact]
        public async Task SharedLibCopy_Identical_Weak()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase = CreateCSharpCompilation(@"
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase.ToMetadataReference() }, lib2Name);
 
            var libBaseImage = libBase.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBaseImage);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBaseImage);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"var l1 = new Lib1();");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
            var s3 = await s2.ContinueWithAsync($@"var l2 = new Lib2();");
            var s4 = await s3.ContinueWithAsync($@"l2.libBase.X");
 
            var c4 = s4.Script.GetCompilation();
            c4.VerifyAssemblyAliases(
                lib2Name,
                lib1Name,
                "mscorlib",
                libBaseName + ": <implicit>,global");
 
            var libBaseRefAndSymbol = c4.GetBoundReferenceManager().GetReferencedAssemblies().ToArray()[3];
            Assert.Equal(fileBase1.Path, ((PortableExecutableReference)libBaseRefAndSymbol.Key).FilePath);
        }
 
        [Fact]
        public async Task SharedLibCopy_Identical_Strong()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase = CreateCSharpCompilation(@"
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase.ToMetadataReference() }, lib2Name);
 
            var libBaseImage = libBase.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBaseImage);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBaseImage);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"var l1 = new Lib1();");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
            var s3 = await s2.ContinueWithAsync($@"var l2 = new Lib2();");
            var s4 = await s3.ContinueWithAsync($@"l2.libBase.X");
 
            var c4 = s4.Script.GetCompilation();
            c4.VerifyAssemblyAliases(
                lib2Name,
                lib1Name,
                "mscorlib",
                libBaseName + ": <implicit>,global");
 
            var libBaseRefAndSymbol = c4.GetBoundReferenceManager().GetReferencedAssemblies().ToArray()[3];
            Assert.Equal(fileBase1.Path, ((PortableExecutableReference)libBaseRefAndSymbol.Key).FilePath);
        }
 
        [Fact]
        public async Task SharedLibCopy_SameVersion_Weak_DifferentContent()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase1 = CreateCSharpCompilation(@"
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName);
 
            var libBase2 = CreateCSharpCompilation(@"
public class LibBase
{
    public readonly int X = 2;
}
", new[] { NetFramework.mscorlib }, libBaseName);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib2Name);
 
            var libBase1Image = libBase1.EmitToArray();
            var libBase2Image = libBase2.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase1Image);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase2Image);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"var l1 = new Lib1();");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
 
            bool exceptionSeen = false;
            try
            {
                await s2.ContinueWithAsync($@"var l2 = new Lib2();");
            }
            catch (FileLoadException fileLoadEx) when (fileLoadEx.InnerException is InteractiveAssemblyLoaderException)
            {
                exceptionSeen = true;
            }
 
            Assert.True(exceptionSeen);
        }
 
        [Fact]
        public async Task SharedLibCopy_SameVersion_Strong_DifferentContent()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase1 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var libBase2 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 2;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib2Name);
 
            var libBase1Image = libBase1.EmitToArray();
            var libBase2Image = libBase2.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase1Image);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase2Image);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"new Lib1().libBase.X");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
 
            bool exceptionSeen = false;
            try
            {
                await s2.ContinueWithAsync($@"new Lib2().libBase.X");
            }
            catch (FileLoadException fileLoadEx) when (fileLoadEx.InnerException is InteractiveAssemblyLoaderException)
            {
                exceptionSeen = true;
            }
 
            Assert.True(exceptionSeen);
        }
 
        [Fact]
        public async Task SharedLibCopy_SameVersion_StrongWeak_DifferentContent()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase1 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var libBase2 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 2;
}
", new[] { NetFramework.mscorlib }, libBaseName);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib2Name);
 
            var libBase1Image = libBase1.EmitToArray();
            var libBase2Image = libBase2.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase1Image);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase2Image);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"new Lib1().libBase.X");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
 
            bool exceptionSeen = false;
            try
            {
                await s2.ContinueWithAsync($@"new Lib2().libBase.X");
            }
            catch (FileLoadException fileLoadEx) when (fileLoadEx.InnerException is InteractiveAssemblyLoaderException)
            {
                exceptionSeen = true;
            }
 
            Assert.True(exceptionSeen);
        }
 
        [Fact]
        public async Task SharedLibCopy_SameVersion_StrongDifferentPKT_DifferentContent()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase1 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var libBase2 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 2;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll2);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib2Name);
 
            var libBase1Image = libBase1.EmitToArray();
            var libBase2Image = libBase2.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase1Image);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase2Image);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"new Lib1().libBase.X");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
 
            bool exceptionSeen = false;
            try
            {
                await s2.ContinueWithAsync($@"new Lib2().libBase.X");
            }
            catch (FileLoadException fileLoadEx) when (fileLoadEx.InnerException is InteractiveAssemblyLoaderException)
            {
                exceptionSeen = true;
            }
 
            Assert.True(exceptionSeen);
        }
 
        [Fact]
        public async Task SharedLibCopy_DifferentVersion_Weak()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase1 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName);
 
            var libBase2 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""2.0.0.0"")]
public class LibBase
{
    public readonly int X = 2;
}
", new[] { NetFramework.mscorlib }, libBaseName);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase2.ToMetadataReference() }, lib2Name);
 
            var libBase1Image = libBase1.EmitToArray();
            var libBase2Image = libBase2.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase1Image);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase2Image);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"var l1 = new Lib1().libBase.X;");
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
 
            bool exceptionSeen = false;
            try
            {
                await s2.ContinueWithAsync($@"var l2 = new Lib2().libBase.X;");
            }
            catch (FileLoadException fileLoadEx) when (fileLoadEx.InnerException is InteractiveAssemblyLoaderException)
            {
                exceptionSeen = true;
            }
 
            Assert.True(exceptionSeen);
        }
 
        [Fact]
        public async Task SharedLibCopy_DifferentVersion_Strong()
        {
            string libBaseName = "LibBase_" + Guid.NewGuid();
            string lib1Name = "Lib1_" + Guid.NewGuid();
            string lib2Name = "Lib2_" + Guid.NewGuid();
 
            var libBase1 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
public class LibBase
{
    public readonly int X = 1;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var libBase2 = CreateCSharpCompilation(@"
[assembly: System.Reflection.AssemblyVersion(""2.0.0.0"")]
public class LibBase
{
    public readonly int X = 2;
}
", new[] { NetFramework.mscorlib }, libBaseName, s_signedDll);
 
            var lib1 = CreateCSharpCompilation(@"
public class Lib1
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase1.ToMetadataReference() }, lib1Name);
 
            var lib2 = CreateCSharpCompilation(@"
public class Lib2
{
    public LibBase libBase = new LibBase();
}
", new MetadataReference[] { NetFramework.mscorlib, libBase2.ToMetadataReference() }, lib2Name);
 
            var libBase1Image = libBase1.EmitToArray();
            var libBase2Image = libBase2.EmitToArray();
            var lib1Image = lib1.EmitToArray();
            var lib2Image = lib2.EmitToArray();
 
            var root = Temp.CreateDirectory();
            var dir1 = root.CreateDirectory("1");
            var file1 = dir1.CreateFile(lib1Name + ".dll").WriteAllBytes(lib1Image);
            var fileBase1 = dir1.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase1Image);
 
            var dir2 = root.CreateDirectory("2");
            var file2 = dir2.CreateFile(lib2Name + ".dll").WriteAllBytes(lib2Image);
            var fileBase2 = dir2.CreateFile(libBaseName + ".dll").WriteAllBytes(libBase2Image);
 
            var s0 = await CSharpScript.RunAsync($@"#r ""{file1.Path}""", ScriptOptions);
            var s1 = await s0.ContinueWithAsync($@"new Lib1().libBase.X");
            Assert.Equal(1, s1.ReturnValue);
            var s2 = await s1.ContinueWithAsync($@"#r ""{file2.Path}""");
            var s3 = await s2.ContinueWithAsync($@"new Lib2().libBase.X");
            Assert.Equal(2, s3.ReturnValue);
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/6457")]
        public async Task MissingReferencesReuse()
        {
            var source = @"
public class C
{
    public System.Diagnostics.Process P;
}
";
 
            var lib = CSharpCompilation.Create(
                "Lib",
                new[] { SyntaxFactory.ParseSyntaxTree(source) },
                new[] { NetFramework.mscorlib, NetFramework.System },
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
 
            var libFile = Temp.CreateFile("lib").WriteAllBytes(lib.EmitToArray());
 
            var s0 = await CSharpScript.RunAsync("C c;", ScriptOptions.WithReferences(libFile.Path));
            await s0.ContinueWithAsync("c = new C()");
        }
    }
}