aspnetcore/test/Microsoft.AspNet.Mvc.Razor..../Compilation/CompilerCacheTest.cs

229 lines
8.1 KiB
C#

// Copyright (c) Microsoft Open Technologies, Inc. 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.Text;
using Microsoft.AspNet.FileSystems;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor.Test
{
public class CompilerCacheTest
{
[Fact]
public void GetOrAdd_ReturnsCompilationResultFromFactory()
{
// Arrange
var cache = new CompilerCache();
var fileInfo = new Mock<IFileInfo>();
fileInfo
.SetupGet(i => i.LastModified)
.Returns(DateTime.FromFileTimeUtc(10000));
var type = GetType();
var expected = UncachedCompilationResult.Successful(type, "hello world");
var runtimeFileInfo = new RelativeFileInfo()
{
FileInfo = fileInfo.Object,
RelativePath = "ab",
};
// Act
var actual = cache.GetOrAdd(runtimeFileInfo, false, () => expected);
// Assert
Assert.Same(expected, actual);
Assert.Equal("hello world", actual.CompiledContent);
Assert.Same(type, actual.CompiledType);
}
private abstract class View
{
public abstract string Content { get; }
}
private class PreCompile : View
{
public override string Content { get { return "Hello World it's @DateTime.Now"; } }
}
private class RuntimeCompileIdentical : View
{
public override string Content { get { return new PreCompile().Content; } }
}
private class RuntimeCompileDifferent : View
{
public override string Content { get { return new PreCompile().Content.Substring(1) + " "; } }
}
private class RuntimeCompileDifferentLength : View
{
public override string Content
{
get
{
return new PreCompile().Content + " longer because it was modified at runtime";
}
}
}
private class ViewCollection : RazorFileInfoCollection
{
public ViewCollection()
{
var fileInfos = new List<RazorFileInfo>();
FileInfos = fileInfos;
var content = new PreCompile().Content;
var length = Encoding.UTF8.GetByteCount(content);
fileInfos.Add(new RazorFileInfo()
{
FullTypeName = typeof(PreCompile).FullName,
Hash = RazorFileHash.GetHash(GetMemoryStream(content)),
LastModified = DateTime.FromFileTimeUtc(10000),
Length = length,
RelativePath = "ab",
});
}
}
private static Stream GetMemoryStream(string content)
{
var bytes = Encoding.UTF8.GetBytes(content);
return new MemoryStream(bytes);
}
[Theory]
[InlineData(typeof(RuntimeCompileIdentical), 10000, false)]
[InlineData(typeof(RuntimeCompileIdentical), 11000, false)]
[InlineData(typeof(RuntimeCompileDifferent), 10000, false)] // expected failure: same time and length
[InlineData(typeof(RuntimeCompileDifferent), 11000, true)]
[InlineData(typeof(RuntimeCompileDifferentLength), 10000, true)]
[InlineData(typeof(RuntimeCompileDifferentLength), 10000, true)]
public void FileWithTheSameLengthAndDifferentTime_DoesNot_OverridesPrecompilation(
Type resultViewType,
long fileTimeUTC,
bool swapsPreCompile)
{
// Arrange
var instance = (View)Activator.CreateInstance(resultViewType);
var length = Encoding.UTF8.GetByteCount(instance.Content);
var collection = new ViewCollection();
var cache = new CompilerCache(new[] { new ViewCollection() });
var fileInfo = new Mock<IFileInfo>();
fileInfo
.SetupGet(i => i.Length)
.Returns(length);
fileInfo
.SetupGet(i => i.LastModified)
.Returns(DateTime.FromFileTimeUtc(fileTimeUTC));
fileInfo.Setup(i => i.CreateReadStream())
.Returns(GetMemoryStream(instance.Content));
var preCompileType = typeof(PreCompile);
var runtimeFileInfo = new RelativeFileInfo()
{
FileInfo = fileInfo.Object,
RelativePath = "ab",
};
// Act
var actual = cache.GetOrAdd(runtimeFileInfo,
enableInstrumentation: false,
compile: () => CompilationResult.Successful(resultViewType));
// Assert
if (swapsPreCompile)
{
Assert.Equal(actual.CompiledType, resultViewType);
}
else
{
Assert.Equal(actual.CompiledType, typeof(PreCompile));
}
}
[Fact]
public void GetOrAdd_DoesNotCacheCompiledContent_OnCallsAfterInitial()
{
// Arrange
var lastModified = DateTime.UtcNow;
var cache = new CompilerCache();
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(f => f.PhysicalPath)
.Returns("test");
fileInfo.SetupGet(f => f.LastModified)
.Returns(lastModified);
var type = GetType();
var uncachedResult = UncachedCompilationResult.Successful(type, "hello world");
var runtimeFileInfo = new RelativeFileInfo()
{
FileInfo = fileInfo.Object,
RelativePath = "test",
};
// Act
cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult);
var actual1 = cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult);
var actual2 = cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult);
// Assert
Assert.NotSame(uncachedResult, actual1);
Assert.NotSame(uncachedResult, actual2);
var result = Assert.IsType<CompilationResult>(actual1);
Assert.Null(actual1.CompiledContent);
Assert.Same(type, actual1.CompiledType);
result = Assert.IsType<CompilationResult>(actual2);
Assert.Null(actual2.CompiledContent);
Assert.Same(type, actual2.CompiledType);
}
[Fact]
public void GetOrAdd_IgnoresCache_IfCachedItemIsNotInstrumentedAndEnableInstrumentationIsTrue()
{
// Arrange
var lastModified = DateTime.UtcNow;
var cache = new CompilerCache();
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(f => f.PhysicalPath)
.Returns("test");
fileInfo.SetupGet(f => f.LastModified)
.Returns(lastModified);
var type = GetType();
var uncachedResult1 = UncachedCompilationResult.Successful(type, "hello world");
var uncachedResult2 = UncachedCompilationResult.Successful(typeof(object), "hello world");
var uncachedResult3 = UncachedCompilationResult.Successful(typeof(Guid), "hello world");
var runtimeFileInfo = new RelativeFileInfo()
{
FileInfo = fileInfo.Object,
RelativePath = "test",
};
// Act
cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult1);
var actual1 = cache.GetOrAdd(runtimeFileInfo, true, () => uncachedResult2);
var actual2 = cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult3);
// Assert
Assert.Same(uncachedResult2, actual1);
Assert.Same(typeof(object), actual1.CompiledType);
Assert.NotSame(actual2, uncachedResult3);
Assert.Same(typeof(object), actual2.CompiledType);
}
}
}