Fix projectmodel-server regression

1. Address the null reference exception when a project dependency is
broken.
2. Address the duplicate key issues after the logic of redirecting
System pacage to reference assembly was added

Update projectmodel-server and tests

1. Fix test timeout caused by undisconnected socket;
2. Update project model server
This commit is contained in:
Troy Dai 2016-01-29 01:49:56 -08:00
parent c4b3925e46
commit b9f2d8fe3d
12 changed files with 81 additions and 48 deletions

View file

@ -156,6 +156,18 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
private LibraryExport ExportProject(ProjectDescription project)
{
if (!project.Resolved)
{
// For a unresolved project reference returns a export with empty asset.
return new LibraryExport(library: project,
compileAssemblies: Enumerable.Empty<LibraryAsset>(),
sourceReferences: Enumerable.Empty<string>(),
nativeLibraries: Enumerable.Empty<LibraryAsset>(),
runtimeAssets: Enumerable.Empty<string>(),
runtimeAssemblies: Array.Empty<LibraryAsset>(),
analyzers: Array.Empty<AnalyzerReference>());
}
var compileAssemblies = new List<LibraryAsset>();
var runtimeAssets = new List<string>();
var sourceReferences = new List<string>();
@ -174,7 +186,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
compileAssemblies.Add(compileAsset);
runtimeAssets.Add(pdbPath);
}
else if(project.Project.Files.SourceFiles.Any())
else if (project.Project.Files.SourceFiles.Any())
{
var outputCalculator = project.GetOutputPathCalculator();
var assemblyPath = outputCalculator.GetAssemblyPath(_configuration);

View file

@ -41,7 +41,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
public override string ToString()
{
return Value;
return Value ?? nameof(Unspecified);
}
public bool CanSatisfyConstraint(LibraryType constraint)

View file

@ -267,6 +267,7 @@ namespace Microsoft.DotNet.ProjectModel
ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver,
out bool requiresFrameworkAssemblies)
{
// Remark: the LibraryType in the key of the given dictionary are all "Unspecified" at the beginning.
requiresFrameworkAssemblies = false;
foreach (var pair in libraries.ToList())
@ -294,41 +295,50 @@ namespace Microsoft.DotNet.ProjectModel
// Remove the original package reference
libraries.Remove(pair.Key);
// Add the reference to the refernce assembly.
libraries[new LibraryKey(replacement.Identity.Name)] = replacement;
continue;
// Insert a reference assembly key if there isn't one
var key = new LibraryKey(replacement.Identity.Name, LibraryType.ReferenceAssembly);
if (!libraries.ContainsKey(key))
{
libraries[key] = replacement;
}
}
}
}
foreach (var pair in libraries.ToList())
{
var library = pair.Value;
library.Framework = library.Framework ?? TargetFramework;
foreach (var dependency in library.Dependencies)
{
var keyType = dependency.Target == LibraryType.ReferenceAssembly ? LibraryType.ReferenceAssembly : LibraryType.Unspecified;
var keyType = dependency.Target == LibraryType.ReferenceAssembly ?
LibraryType.ReferenceAssembly :
LibraryType.Unspecified;
var key = new LibraryKey(dependency.Name, keyType);
LibraryDescription dep;
if (!libraries.TryGetValue(key, out dep))
LibraryDescription dependencyDescription;
if (!libraries.TryGetValue(key, out dependencyDescription))
{
if (Equals(LibraryType.ReferenceAssembly, dependency.Target))
if (keyType == LibraryType.ReferenceAssembly)
{
requiresFrameworkAssemblies = true;
dep = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ??
UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
dep.Framework = TargetFramework;
libraries[key] = dep;
// a dependency is specified to be reference assembly but fail to match
// then add a unresolved dependency
dependencyDescription = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ??
UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
libraries[key] = dependencyDescription;
}
else
else if (!libraries.TryGetValue(new LibraryKey(dependency.Name, LibraryType.ReferenceAssembly), out dependencyDescription))
{
dep = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
libraries[key] = dep;
// a dependency which type is unspecified fails to match, then try to find a
// reference assembly type dependency
dependencyDescription = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
libraries[key] = dependencyDescription;
}
}
dep.RequestedRanges.Add(dependency);
dep.Parents.Add(library);
dependencyDescription.RequestedRanges.Add(dependency);
dependencyDescription.Parents.Add(library);
}
}
}

View file

@ -63,7 +63,7 @@ namespace Microsoft.DotNet.ProjectModel.Resolution
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// There is no reference assemblies path outside of windows
// The enviorment variable can be used to specify one
// The environment variable can be used to specify one
return null;
}

View file

@ -34,7 +34,8 @@ namespace Microsoft.DotNet.ProjectModel.Server
var allExports = context.CreateExporter(configuration)
.GetAllExports()
.ToDictionary(export => export.Library.GetUniqueName());
.ToDictionary(export => export.Library.Identity.Name);
var allSourceFiles = new List<string>(context.ProjectFile.Files.SourceFiles);
var allFileReferences = new List<string>();
var allProjectReferences = new List<ProjectReferenceDescription>();
@ -42,10 +43,8 @@ namespace Microsoft.DotNet.ProjectModel.Server
// All exports are returned. When the same library name have a ReferenceAssembly type export and a Package type export
// both will be listed as dependencies. Prefix "fx/" will be added to ReferenceAssembly type dependency.
foreach (var pair in allExports)
foreach (var export in allExports.Values)
{
var export = pair.Value;
allSourceFiles.AddRange(export.SourceReferences);
allFileReferences.AddRange(export.CompilationAssemblies.Select(asset => asset.ResolvedPath));

View file

@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.ProjectModel.Compilation;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.ProjectModel.Server.Helpers;
namespace Microsoft.DotNet.ProjectModel.Server.Models
@ -54,27 +55,32 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models
public static DependencyDescription Create(LibraryDescription library,
List<DiagnosticMessage> diagnostics,
Dictionary<string, LibraryExport> allExports)
IDictionary<string, LibraryExport> exportsLookup)
{
var name = library.GetUniqueName();
return new DependencyDescription
{
Name = name,
Name = library.Identity.Name,
DisplayName = library.Identity.Name,
Version = library.Identity.Version?.ToNormalizedString(),
Type = library.Identity.Type.Value,
Resolved = library.Resolved,
Path = library.Path,
Dependencies = library.Dependencies.Select(dependency => new DependencyItem
{
Name = dependency.GetUniqueName(),
Version = allExports[dependency.GetUniqueName()].Library.Identity.Version?.ToNormalizedString()
}),
Dependencies = library.Dependencies.Select(dependency => GetDependencyItem(dependency, exportsLookup)),
Errors = diagnostics.Where(d => d.Severity == DiagnosticMessageSeverity.Error)
.Select(d => new DiagnosticMessageView(d)),
Warnings = diagnostics.Where(d => d.Severity == DiagnosticMessageSeverity.Warning)
.Select(d => new DiagnosticMessageView(d))
};
}
private static DependencyItem GetDependencyItem(LibraryRange dependency,
IDictionary<string, LibraryExport> exportsLookup)
{
return new DependencyItem
{
Name = dependency.Name,
Version = exportsLookup[dependency.Name].Library.Identity.Version?.ToNormalizedString()
};
}
}
}

View file

@ -43,7 +43,7 @@ namespace Microsoft.DotNet.ProjectModel.Server
catch (IOException ex)
{
// swallow
_log.LogWarning($"Ignore {nameof(IOException)} during sending message: \"{ex.Message}\".");
_log.LogInformation($"Ignore {nameof(IOException)} during sending message: \"{ex.Message}\".");
}
catch (Exception ex)
{
@ -79,7 +79,7 @@ namespace Microsoft.DotNet.ProjectModel.Server
}
catch (IOException ex)
{
_log.LogWarning($"Ignore {nameof(IOException)} during receiving messages: \"{ex}\".");
_log.LogInformation($"Ignore {nameof(IOException)} during receiving messages: \"{ex}\".");
}
catch (Exception ex)
{
@ -87,4 +87,4 @@ namespace Microsoft.DotNet.ProjectModel.Server
}
}
}
}
}

View file

@ -9,6 +9,7 @@ using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Xunit;
@ -29,18 +30,19 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
// works in visual studio
private readonly Dictionary<string, int> _projectContexts = new Dictionary<string, int>();
private int _nextContextId;
private readonly Socket _socket;
public DthTestClient(DthTestServer server)
{
var socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Loopback, server.Port));
_socket.Connect(new IPEndPoint(IPAddress.Loopback, server.Port));
_hostId = server.HostId;
_networkStream = new NetworkStream(socket);
_networkStream = new NetworkStream(_socket);
_reader = new BinaryReader(_networkStream);
_writer = new BinaryWriter(_networkStream);
@ -221,6 +223,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
_writer.Dispose();
_networkStream.Dispose();
_readCancellationToken.Cancel();
_socket.Shutdown(SocketShutdown.Both);
}
private void ReadMessage(CancellationToken cancellationToken)

View file

@ -5,13 +5,14 @@ using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.DotNet.ProjectModel.Server;
using Microsoft.Extensions.Logging;
namespace Microsoft.DotNet.ProjectModel.Server.Tests
{
public class DthTestServer : IDisposable
{
private readonly Program _program;
private readonly ProjectModelServerCommand _program;
private readonly Thread _thread;
public DthTestServer(ILoggerFactory loggerFactory)
@ -21,9 +22,9 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
Port = FindFreePort();
HostId = Guid.NewGuid().ToString();
_program = new Program(Port, HostId, LoggerFactory);
_program = new ProjectModelServerCommand(Port, HostId, LoggerFactory);
_thread = new Thread(() => { _program.OpenChannel(); });
_thread = new Thread(() => { _program.OpenChannel(); }) { IsBackground = true };
_thread.Start();
}

View file

@ -86,7 +86,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
[Theory]
[InlineData("Project", "UnresolvedProjectSample", "EmptyLibrary", "Project")]
[InlineData("Package", "UnresolvedPackageSample", "NoSuchPackage", null)]
[InlineData("Package", "IncompatiblePackageSample", "Newtonsoft.Json", "Package")]
[InlineData("Package", "IncompatiblePackageSample", "Microsoft.Web.Administration", "Package")]
public void DthCompilation_Initialize_UnresolvedDependency(string referenceType,
string testProjectName,
string expectedUnresolvedDependency,

View file

@ -1,5 +1,6 @@
{
"dependencies": {
"NETStandard.Library": "1.0.0-rc2-23728",
"EmptyLibrary": ""
},
"frameworks": {

View file

@ -1,6 +1,7 @@
{
"dependencies": {
"Newtonsoft.Json": "4.5.11"
"NETStandard.Library": "1.0.0-rc2-23728",
"Microsoft.Web.Administration": "7.0.0"
},
"frameworks": {
"dnxcore50": {