/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Scripting/CSharpTest.Desktop/InteractiveSessionReferencesTests.cs
1 124 строки
44 KB
Jan Jones
Fix stdlib inconsistency between core and fx compiler (#79911)
25 авг 2025, 12:16
Не верифицирован
25 авг 2025, 12:16
091085e
Код
Авторство
О чём код?
// 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.Scripting.TestUtilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using static Microsoft.CodeAnalysis.Scripting.TestCompilationFactory; using AssertEx = PortableTestUtils::Roslyn.Test.Utilities.AssertEx; using WorkItemAttribute = PortableTestUtils::Roslyn.Test.Utilities.WorkItemAttribute; 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(Skip = "https://github.com/dotnet/roslyn/issues/79923")] 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(Skip = "https://github.com/dotnet/roslyn/issues/79923")] 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()"); } } }