Skip to content
This repository has been archived by the owner on Dec 18, 2017. It is now read-only.

Commit

Permalink
Check for min runtime version at application start
Browse files Browse the repository at this point in the history
  • Loading branch information
Victor Hurdugaci committed Sep 11, 2015
1 parent d689333 commit f228654
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 10 deletions.
5 changes: 3 additions & 2 deletions src/Microsoft.Dnx.ApplicationHost/DefaultHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ private void Initialize(RuntimeOptions options, IServiceProvider hostServices, I
{
ProjectDirectory = _projectDirectory,
RuntimeIdentifiers = _runtimeEnvironment.GetAllRuntimeIdentifiers(),
TargetFramework = _targetFramework
TargetFramework = _targetFramework,
RuntimeEnvironment = _runtimeEnvironment
};

var libraries = ApplicationHostContext.GetRuntimeLibraries(applicationHostContext, throwOnInvalidLockFile: true);
Expand Down Expand Up @@ -145,7 +146,7 @@ private void Initialize(RuntimeOptions options, IServiceProvider hostServices, I
loadContextAccessor.Default,
new CompilationCache(),
fileWatcher,
new ProjectGraphProvider());
new ProjectGraphProvider(_runtimeEnvironment));

// Compilation services available only for runtime compilation
compilationContext.AddCompilationService(typeof(RuntimeOptions), options);
Expand Down
4 changes: 3 additions & 1 deletion src/Microsoft.Dnx.Compilation/CompilationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ public LibraryExporter CreateProjectExporter(Project project, FrameworkName targ
{
Project = project,
RuntimeIdentifiers = _context.RuntimeEnvironment.GetAllRuntimeIdentifiers(),
TargetFramework = _context.ApplicationEnvironment.RuntimeFramework
TargetFramework = _context.ApplicationEnvironment.RuntimeFramework,
SkipRuntimeMinVersionCheck = true,
RuntimeEnvironment = _context.RuntimeEnvironment
};

var libraries = ApplicationHostContext.GetRuntimeLibraries(context);
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Dnx.Compilation/CompilationEngineContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public CompilationEngineContext(IApplicationEnvironment applicationEnvironment,
IRuntimeEnvironment runtimeEnvironment,
IAssemblyLoadContext defaultLoadContext,
CompilationCache cache) :
this(applicationEnvironment, runtimeEnvironment, defaultLoadContext, cache, NoopWatcher.Instance, new ProjectGraphProvider())
this(applicationEnvironment, runtimeEnvironment, defaultLoadContext, cache, NoopWatcher.Instance, new ProjectGraphProvider(runtimeEnvironment))
{

}
Expand Down
10 changes: 9 additions & 1 deletion src/Microsoft.Dnx.Compilation/ProjectGraphProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ namespace Microsoft.Dnx.Compilation
{
public class ProjectGraphProvider : IProjectGraphProvider
{
private readonly IRuntimeEnvironment _runtimeEnvironment;

public ProjectGraphProvider(IRuntimeEnvironment runtimeEnvironment)
{
_runtimeEnvironment = runtimeEnvironment;
}

public LibraryManager GetProjectGraph(Project project, FrameworkName targetFramework)
{
// TODO: Cache sub-graph walk?
Expand All @@ -15,7 +22,8 @@ public LibraryManager GetProjectGraph(Project project, FrameworkName targetFrame
var context = new ApplicationHostContext
{
Project = project,
TargetFramework = targetFramework
TargetFramework = targetFramework,
SkipRuntimeMinVersionCheck = true
};

ApplicationHostContext.Initialize(context);
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.Dnx.DesignTimeHost/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,8 @@ private ApplicationHostContext CreateApplicationHostContext(CacheContext ctx, Pr
TargetFramework = frameworkName,
RuntimeIdentifiers = runtimeIdentifiers,
FrameworkResolver = _frameworkResolver,
SkipLockfileValidation = true
SkipLockfileValidation = true,
RuntimeEnvironment = _runtimeEnvironment
};

ApplicationHostContext.Initialize(applicationHostContext);
Expand Down
39 changes: 37 additions & 2 deletions src/Microsoft.Dnx.Runtime/ApplicationHostContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ public class ApplicationHostContext

public bool SkipLockfileValidation { get; set; }

public bool SkipRuntimeMinVersionCheck { get; set; }

public FrameworkReferenceResolver FrameworkResolver { get; set; }

public LibraryManager LibraryManager { get; private set; }

public IRuntimeEnvironment RuntimeEnvironment { get; set; }

public static IList<LibraryDescription> GetRuntimeLibraries(ApplicationHostContext context)
{
return GetRuntimeLibraries(context, throwOnInvalidLockFile: false);
Expand All @@ -52,6 +56,11 @@ public static IList<LibraryDescription> GetRuntimeLibraries(ApplicationHostConte
}
}

if (!string.IsNullOrEmpty(result.MinRequiredRuntimeVersion))
{
throw new InvalidOperationException($"{context.Project.Name} requires DNX version {result.MinRequiredRuntimeVersion} or newer to run.");
}

return result.Libraries;
}

Expand Down Expand Up @@ -215,7 +224,30 @@ private static Result InitializeCore(ApplicationHostContext context)
var lockFilePresent = context.LockFile != null;
context.LockFile = null; // LockFile is no longer needed

return new Result(libraries, lockFilePresent, validLockFile, lockFileValidationMessage);
string minRequiredRuntime = null;
if (!context.SkipRuntimeMinVersionCheck)
{
LibraryDescription abstractions = null;
foreach (var lib in libraries)
{
// Ignore projects references because in that case we are compiling from sources
// and versions don't match
if (lib.Type == LibraryTypes.Package &&
lib.Identity.Name.Equals("Microsoft.Dnx.Runtime.Abstractions", StringComparison.Ordinal))
{
abstractions = lib;
break;
}
}

if (abstractions != null &&
abstractions.Identity.Version > new NuGet.SemanticVersion(context.RuntimeEnvironment.RuntimeVersion))
{
minRequiredRuntime = abstractions.Identity.Version.ToString();
}
}

return new Result(libraries, lockFilePresent, validLockFile, minRequiredRuntime, lockFileValidationMessage);
}

private static LockFileTarget SelectTarget(ApplicationHostContext context, LockFile lockFile)
Expand Down Expand Up @@ -270,12 +302,15 @@ private struct Result
public bool LockFileExists { get; }
public bool ValidLockFile { get; }

public Result(List<LibraryDescription> libraries, bool lockFileExists, bool validLockFile, string lockFileValidationMessage)
public string MinRequiredRuntimeVersion { get; }

public Result(List<LibraryDescription> libraries, bool lockFileExists, bool validLockFile, string minRequiredRuntimeVersion, string lockFileValidationMessage)
{
Libraries = libraries;
LockFileExists = lockFileExists;
ValidLockFile = validLockFile;
LockFileValidationMessage = lockFileValidationMessage;
MinRequiredRuntimeVersion = minRequiredRuntimeVersion;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.Dnx.Tooling/List/DependencyListOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ private LibraryManager CreateLibraryManager()
var hostContext = new ApplicationHostContext
{
Project = _options.Project,
TargetFramework = _framework
TargetFramework = _framework,
RuntimeEnvironment = RuntimeEnvironmentHelper.RuntimeEnvironment
};

ApplicationHostContext.Initialize(hostContext);
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.Dnx.Tooling/Publish/DependencyContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public DependencyContext(Runtime.Project project, FrameworkName targetFramework)
var applicationHostContext = new ApplicationHostContext
{
Project = project,
TargetFramework = targetFramework
TargetFramework = targetFramework,
RuntimeEnvironment = RuntimeEnvironmentHelper.RuntimeEnvironment
};

ApplicationHostContext.Initialize(applicationHostContext);
Expand Down
125 changes: 125 additions & 0 deletions test/Microsoft.Dnx.Runtime.Tests/Host/MinRuntimeVersionFacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// 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.

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Versioning;
using System.Text;
using NuGet;
using Xunit;

namespace Microsoft.Dnx.Runtime.Tests.Host
{
public class MinRuntimeVersionFacts
{
private const string TooHighVersion = "100.0.0";

private static readonly FrameworkName Dnx451 = new FrameworkName(VersionUtility.DnxFrameworkIdentifier, new Version(4, 5, 1));

[Fact]
public void LoadWithOldRuntime_Throws()
{
var ahc = new ApplicationHostContext()
{
RuntimeEnvironment = RuntimeEnvironmentHelper.RuntimeEnvironment,
Project = CreateDummyProject(),
TargetFramework = Dnx451,
RuntimeIdentifiers = new[] { "win7-x64" },
SkipLockfileValidation = true,
LockFile = CreateLockFile(TooHighVersion)
};

InvalidOperationException exception = Assert.Throws<InvalidOperationException>(() => ApplicationHostContext.GetRuntimeLibraries(ahc));

Assert.Contains(TooHighVersion, exception.Message);
}

[Fact]
public void LoadWithNewerRuntime_NoThrow()
{
var ahc = new ApplicationHostContext()
{
RuntimeEnvironment = RuntimeEnvironmentHelper.RuntimeEnvironment,
Project = CreateDummyProject(),
TargetFramework = Dnx451,
RuntimeIdentifiers = new[] { "win7-x64" },
SkipLockfileValidation = true,
LockFile = CreateLockFile(RuntimeEnvironmentHelper.RuntimeEnvironment.RuntimeVersion)
};

try
{
ApplicationHostContext.GetRuntimeLibraries(ahc);
}
catch
{
Assert.True(false, "No exception was expected");
}
}

[Fact]
public void DisableMinVersionCheck()
{
var ahc = new ApplicationHostContext()
{
RuntimeEnvironment = RuntimeEnvironmentHelper.RuntimeEnvironment,
SkipRuntimeMinVersionCheck = true,
Project = CreateDummyProject(),
TargetFramework = Dnx451,
RuntimeIdentifiers = new[] { "win7-x64" },
SkipLockfileValidation = true,
LockFile = CreateLockFile(TooHighVersion)
};

try
{
ApplicationHostContext.GetRuntimeLibraries(ahc);
}
catch
{
Assert.True(false, "No exception was expected");
}
}

private Project CreateDummyProject()
{
const string DummyProject = @"{ ""frameworks"": { ""dnx451"": {} } }";
using (var strm = new MemoryStream(Encoding.UTF8.GetBytes(DummyProject)))
{
return new ProjectReader().ReadProject(strm, "DummyProject", @"C:\DummyProject", new List<DiagnosticMessage>());
}
}

private LockFile CreateLockFile(string runtimeVersion)
{
return new LockFile()
{
Version = Constants.LockFileVersion,
Targets = new List<LockFileTarget>()
{
new LockFileTarget()
{
TargetFramework = Dnx451,
Libraries =new LockFileTargetLibrary[]
{
new LockFileTargetLibrary()
{
Name = "Microsoft.Dnx.Runtime.Abstractions",
Version = new SemanticVersion(runtimeVersion)
}
}
}
},
PackageLibraries = new List<LockFilePackageLibrary>()
{
new LockFilePackageLibrary()
{
Name = "Microsoft.Dnx.Runtime.Abstractions",
Version = new SemanticVersion(runtimeVersion)
},
}
};
}
}
}

0 comments on commit f228654

Please sign in to comment.