Make ReferencedAssemblyFileProviderTest more useful
This commit is contained in:
parent
5ec2a5eb1e
commit
4b247e8050
|
|
@ -13,7 +13,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\samples\HostedInAspNet.Client\HostedInAspNet.Client.csproj" />
|
||||
<ProjectReference Include="..\samples\StandaloneApp\StandaloneApp.csproj" />
|
||||
<ProjectReference Include="..\src\Microsoft.Blazor.Server\Microsoft.Blazor.Server.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Blazor.Mono;
|
||||
using Mono.Cecil;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -12,8 +15,10 @@ namespace Microsoft.Blazor.Server.Test
|
|||
[Fact]
|
||||
public void RootDirContainsOnlyBinDir()
|
||||
{
|
||||
var (entrypoint, entrypointData) = GetBclAssemblyForTest("mscorlib");
|
||||
var provider = new ReferencedAssemblyFileProvider(
|
||||
typeof (HostedInAspNet.Client.Program).Assembly,
|
||||
entrypoint,
|
||||
entrypointData,
|
||||
MonoStaticFileProvider.Instance);
|
||||
Assert.Collection(provider.GetDirectoryContents("/"), item =>
|
||||
{
|
||||
|
|
@ -23,19 +28,89 @@ namespace Microsoft.Blazor.Server.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void FindsEntrypointAssemblyAndReferencedAssemblies()
|
||||
public void FindsReferencedAssemblyGraphSimple()
|
||||
{
|
||||
var (entrypoint, entrypointData) = GetBclAssemblyForTest("System.Linq.Expressions");
|
||||
var provider = new ReferencedAssemblyFileProvider(
|
||||
typeof(HostedInAspNet.Client.Program).Assembly,
|
||||
entrypoint,
|
||||
entrypointData,
|
||||
MonoStaticFileProvider.Instance);
|
||||
var contents = provider.GetDirectoryContents("/bin").OrderBy(i => i.Name).ToList();
|
||||
Assert.Collection(contents,
|
||||
item => { Assert.Equal("/bin/HostedInAspNet.Client.dll", item.PhysicalPath); },
|
||||
item => { Assert.Equal("/bin/mscorlib.dll", item.PhysicalPath); },
|
||||
item => { Assert.Equal("/bin/System.Console.dll", item.PhysicalPath); },
|
||||
item => { Assert.Equal("/bin/System.Core.dll", item.PhysicalPath); },
|
||||
item => { Assert.Equal("/bin/System.dll", item.PhysicalPath); },
|
||||
item => { Assert.Equal("/bin/System.Runtime.dll", item.PhysicalPath); });
|
||||
item => { Assert.Equal("/bin/System.Linq.Expressions.dll", item.PhysicalPath); });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindsReferencedAssemblyGraphRealistic()
|
||||
{
|
||||
// Arrange
|
||||
var standaloneAppAssemblyLocation = typeof(StandaloneApp.Program).Assembly.Location;
|
||||
var provider = new ReferencedAssemblyFileProvider(
|
||||
AssemblyDefinition.ReadAssembly(standaloneAppAssemblyLocation),
|
||||
File.ReadAllBytes(standaloneAppAssemblyLocation),
|
||||
MonoStaticFileProvider.Instance);
|
||||
var expectedContents = new[]
|
||||
{
|
||||
/*
|
||||
The current Mono WASM BCL forwards from netstandard.dll to various facade assemblies
|
||||
in which small bits of implementation live, such as System.Xml.XPath.XDocument. So
|
||||
if you reference netstandard, then you also reference System.Xml.XPath.XDocument.dll,
|
||||
even though you're very unlikely to be calling it at runtime. That's why the following
|
||||
list (for a very basic Blazor app) is longer than you'd expect.
|
||||
|
||||
These redundant references could be stripped out during publishing, but it's still
|
||||
unfortunate that in development mode you'd see all these unexpected assemblies get
|
||||
fetched from the server. We should try to get the Mono WASM BCL reorganized so that
|
||||
all the implementation goes into mscorlib.dll, with the facade assemblies existing only
|
||||
in case someone (or some 3rd party assembly) references them directly, but with their
|
||||
implementations 100% forwarding to mscorlib.dll. Then in development you'd fetch far
|
||||
fewer assemblies from the server, and during publishing, illink would remove all the
|
||||
uncalled implementation code from mscorlib.dll anyway.
|
||||
*/
|
||||
"/bin/Microsoft.Blazor.dll",
|
||||
"/bin/mscorlib.dll",
|
||||
"/bin/netstandard.dll",
|
||||
"/bin/StandaloneApp.dll",
|
||||
"/bin/System.Console.dll",
|
||||
"/bin/System.Core.dll",
|
||||
"/bin/System.Diagnostics.StackTrace.dll",
|
||||
"/bin/System.dll",
|
||||
"/bin/System.Globalization.Extensions.dll",
|
||||
"/bin/System.Runtime.dll",
|
||||
"/bin/System.Runtime.InteropServices.RuntimeInformation.dll",
|
||||
"/bin/System.Runtime.Serialization.Primitives.dll",
|
||||
"/bin/System.Runtime.Serialization.Xml.dll",
|
||||
"/bin/System.Security.Cryptography.Algorithms.dll",
|
||||
"/bin/System.Security.SecureString.dll",
|
||||
"/bin/System.Xml.XPath.XDocument.dll",
|
||||
};
|
||||
|
||||
// Act
|
||||
var contents = provider.GetDirectoryContents("/bin")
|
||||
.OrderBy(i => i.Name, StringComparer.InvariantCulture).ToList();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedContents.Length, contents.Count);
|
||||
for (var i = 0; i < expectedContents.Length; i++)
|
||||
{
|
||||
Assert.Equal(expectedContents[i], contents[i].PhysicalPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static (AssemblyDefinition, byte[]) GetBclAssemblyForTest(string name)
|
||||
{
|
||||
var possibleFilenames = new[] { $"/bcl/{name}.dll", $"/bcl/Facades/{name}.dll" };
|
||||
var fileInfo = possibleFilenames
|
||||
.Select(MonoStaticFileProvider.Instance.GetFileInfo)
|
||||
.First(item => item.Exists);
|
||||
using (var data = new MemoryStream())
|
||||
{
|
||||
fileInfo.CreateReadStream().CopyTo(data);
|
||||
return (AssemblyDefinition.ReadAssembly(fileInfo.CreateReadStream()), data.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace StandaloneApp
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello, world!");
|
||||
Console.WriteLine(Microsoft.Blazor.Test.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
-->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Blazor.DevHost\Microsoft.Blazor.DevHost.csproj" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Blazor\Microsoft.Blazor.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RunArguments>run --project ..\..\src\Microsoft.Blazor.DevHost --no-build serve</RunArguments>
|
||||
|
|
|
|||
|
|
@ -14,20 +14,21 @@ namespace Microsoft.Blazor.Server
|
|||
{
|
||||
internal class ReferencedAssemblyFileProvider : InMemoryFileProvider
|
||||
{
|
||||
public ReferencedAssemblyFileProvider(Assembly entrypointAssembly, IFileProvider clientBcl)
|
||||
: base(ComputeContents(entrypointAssembly, clientBcl))
|
||||
public ReferencedAssemblyFileProvider(
|
||||
AssemblyDefinition entrypoint,
|
||||
byte[] entrypointData,
|
||||
IFileProvider clientBcl)
|
||||
: base(ComputeContents(entrypoint, entrypointData, clientBcl))
|
||||
{
|
||||
}
|
||||
|
||||
private static IEnumerable<(string, Stream)> ComputeContents(
|
||||
Assembly entrypointAssembly,
|
||||
AssemblyDefinition entrypoint,
|
||||
byte[] entrypointData,
|
||||
IFileProvider clientBcl)
|
||||
{
|
||||
var foundAssemblies = new Dictionary<string, ReferencedAssembly>();
|
||||
AddWithReferencesRecursive(
|
||||
new ReferencedAssembly(AssemblyDefinition.ReadAssembly(entrypointAssembly.Location)),
|
||||
clientBcl,
|
||||
foundAssemblies);
|
||||
AddWithReferencesRecursive(new ReferencedAssembly(entrypoint, entrypointData), clientBcl, foundAssemblies);
|
||||
|
||||
return foundAssemblies.Values.Select(assembly => (
|
||||
$"/bin/{assembly.Name}.dll",
|
||||
|
|
@ -72,7 +73,9 @@ namespace Microsoft.Blazor.Server
|
|||
// (e.g., if it's in the app's bin directory, or a NuGet package)
|
||||
var nativelyResolved = module.AssemblyResolver.Resolve(referenceName);
|
||||
return AllowServingAssembly(nativelyResolved)
|
||||
? new ReferencedAssembly(nativelyResolved)
|
||||
? new ReferencedAssembly(
|
||||
nativelyResolved,
|
||||
File.ReadAllBytes(nativelyResolved.MainModule.FileName))
|
||||
: null;
|
||||
}
|
||||
catch (AssemblyResolutionException)
|
||||
|
|
@ -128,10 +131,10 @@ namespace Microsoft.Blazor.Server
|
|||
public byte[] Data { get; }
|
||||
public AssemblyDefinition Definition { get; }
|
||||
|
||||
public ReferencedAssembly(AssemblyDefinition definition)
|
||||
public ReferencedAssembly(AssemblyDefinition definition, byte[] rawData)
|
||||
{
|
||||
Name = definition.Name.Name;
|
||||
Data = File.ReadAllBytes(definition.MainModule.FileName);
|
||||
Data = rawData;
|
||||
Definition = definition;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.Blazor
|
||||
{
|
||||
public static class Test
|
||||
{
|
||||
public readonly static string Message = "Hello, world!";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue