Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SqlServerCe.4.0"></remove>
<add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
</DbProviderFactories>
</system.data>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<!-- Need this because the BinarySerializer uses the TypeForwardedFrom attribute and deserializes to the original assembly (MVC 2.0) for the HttpAntiForgeryException test -->
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -0,0 +1,152 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.WebPages.ApplicationParts;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.WebPages.Test.ApplicationModule
{
public class ApplicationPartRegistryTest
{
[Fact]
public void ApplicationModuleGeneratesRootRelativePaths()
{
// Arrange
var path1 = "foo/bar";
var path2 = "~/xyz/pqr";
var root1 = "~/myappmodule";
var root2 = "~/myappmodule2/";
// Act
var actualPath11 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root1, path1);
var actualPath12 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root1, path2);
var actualPath21 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root2, path1);
var actualPath22 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root2, path2);
// Assert
Assert.Equal(actualPath11, root1 + "/" + path1);
Assert.Equal(actualPath12, root1 + path2.TrimStart('~'));
Assert.Equal(actualPath21, root2 + path1);
Assert.Equal(actualPath22, root2 + path2.TrimStart('~', '/'));
}
[Fact]
public void ApplicationPartRegistryLooksUpPartsByName()
{
// Arrange
var part = new ApplicationPart(BuildAssembly(), "~/mymodule");
var dictionary = new DictionaryBasedVirtualPathFactory();
var registry = new ApplicationPartRegistry(dictionary);
Func<object> myFunc = () => "foo";
// Act
registry.Register(part, myFunc);
// Assert
Assert.Equal(registry["my-assembly"], part);
Assert.Equal(registry["MY-aSSembly"], part);
}
[Fact]
public void ApplicationPartRegistryLooksUpPartsByAssembly()
{
// Arrange
var assembly = BuildAssembly();
var part = new ApplicationPart(assembly, "~/mymodule");
var dictionary = new DictionaryBasedVirtualPathFactory();
var registry = new ApplicationPartRegistry(dictionary);
Func<object> myFunc = () => "foo";
// Act
registry.Register(part, myFunc);
// Assert
Assert.Equal(registry[assembly], part);
}
[Fact]
public void RegisterThrowsIfAssemblyAlreadyRegistered()
{
// Arrange
var part = new ApplicationPart(BuildAssembly(), "~/mymodule");
var dictionary = new DictionaryBasedVirtualPathFactory();
var registry = new ApplicationPartRegistry(dictionary);
Func<object> myFunc = () => "foo";
// Act
registry.Register(part, myFunc);
// Assert
Assert.Throws<InvalidOperationException>(() => registry.Register(part, myFunc),
String.Format("The assembly \"{0}\" is already registered.", part.Assembly.ToString()));
}
[Fact]
public void RegisterThrowsIfPathAlreadyRegistered()
{
// Arrange
var part = new ApplicationPart(BuildAssembly(), "~/mymodule");
var dictionary = new DictionaryBasedVirtualPathFactory();
var registry = new ApplicationPartRegistry(dictionary);
Func<object> myFunc = () => "foo";
// Act
registry.Register(part, myFunc);
// Assert
var newPart = new ApplicationPart(BuildAssembly("different-assembly"), "~/mymodule");
Assert.Throws<InvalidOperationException>(() => registry.Register(newPart, myFunc),
"An application module is already registered for virtual path \"~/mymodule/\".");
}
[Fact]
public void RegisterCreatesRoutesForValidPages()
{
// Arrange
var part = new ApplicationPart(BuildAssembly(), "~/mymodule");
var dictionary = new DictionaryBasedVirtualPathFactory();
var registry = new ApplicationPartRegistry(dictionary);
Func<object> myFunc = () => "foo";
// Act
registry.Register(part, myFunc);
// Assert
Assert.True(dictionary.Exists("~/mymodule/Page1"));
Assert.Equal(dictionary.CreateInstance("~/mymodule/Page1"), "foo");
Assert.False(dictionary.Exists("~/mymodule/Page2"));
Assert.False(dictionary.Exists("~/mymodule/Page3"));
}
private static IResourceAssembly BuildAssembly(string name = "my-assembly")
{
Mock<TestResourceAssembly> assembly = new Mock<TestResourceAssembly>();
assembly.SetupGet(c => c.Name).Returns(name);
assembly.Setup(c => c.GetHashCode()).Returns(name.GetHashCode());
assembly.Setup(c => c.Equals(It.IsAny<TestResourceAssembly>())).Returns((TestResourceAssembly c) => c.Name == name);
assembly.Setup(c => c.GetTypes()).Returns(new[]
{
BuildPageType(inherits: true, virtualPath: "~/Page1"),
BuildPageType(inherits: true, virtualPath: null),
BuildPageType(inherits: false, virtualPath: "~/Page3"),
});
return assembly.Object;
}
private static Type BuildPageType(bool inherits, string virtualPath)
{
Mock<Type> type = new Mock<Type>();
type.Setup(c => c.IsSubclassOf(typeof(WebPageRenderingBase))).Returns(inherits);
if (virtualPath != null)
{
type.Setup(c => c.GetCustomAttributes(typeof(PageVirtualPathAttribute), false))
.Returns(new[] { new PageVirtualPathAttribute(virtualPath) });
}
return type.Object;
}
}
}

View File

@ -0,0 +1,200 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.WebPages.Test
{
public class ApplicationPartTest
{
[Fact]
public void ApplicationPartThrowsIfRootVirtualPathIsNullOrEmpty()
{
// Arrange
var assembly = new Mock<TestResourceAssembly>().Object;
Assert.ThrowsArgumentNullOrEmptyString(() => new ApplicationPart(assembly, rootVirtualPath: null), "rootVirtualPath");
Assert.ThrowsArgumentNullOrEmptyString(() => new ApplicationPart(assembly, rootVirtualPath: String.Empty), "rootVirtualPath");
}
[Fact]
public void ResolveVirtualPathResolvesRegularPathsUsingBaseVirtualPath()
{
// Arrange
var basePath = "~/base/";
var path = "somefile";
var appPartRoot = "~/app/";
// Act
var virtualPath = ApplicationPart.ResolveVirtualPath(appPartRoot, basePath, path);
// Assert
Assert.Equal(virtualPath, "~/base/somefile");
}
[Fact]
public void ResolveVirtualPathResolvesAppRelativePathsUsingAppVirtualPath()
{
// Arrange
var basePath = "~/base";
var path = "@/somefile";
var appPartRoot = "~/app/";
// Act
var virtualPath = ApplicationPart.ResolveVirtualPath(appPartRoot, basePath, path);
// Assert
Assert.Equal(virtualPath, "~/app/somefile");
}
[Fact]
public void ResolveVirtualPathDoesNotAffectRootRelativePaths()
{
// Arrange
var basePath = "~/base";
var path = "~/somefile";
var appPartRoot = "~/app/";
// Act
var virtualPath = ApplicationPart.ResolveVirtualPath(appPartRoot, basePath, path);
// Assert
Assert.Equal(virtualPath, "~/somefile");
}
[Fact]
public void GetResourceNameFromVirtualPathForTopLevelPath()
{
// Arrange
var moduleName = "my-module";
var path = "foo.baz";
// Act
var name = ApplicationPart.GetResourceNameFromVirtualPath(moduleName, path);
// Assert
Assert.Equal(name, moduleName + "." + path);
}
[Fact]
public void GetResourceNameFromVirtualPathForItemInSubDir()
{
// Arrange
var moduleName = "my-module";
var path = "/bar/foo";
// Act
var name = ApplicationPart.GetResourceNameFromVirtualPath(moduleName, path);
// Assert
Assert.Equal(name, "my-module.bar.foo");
}
[Fact]
public void GetResourceNameFromVirtualPathForItemWithSpaces()
{
// Arrange
var moduleName = "my-module";
var path = "/program files/data files/my file .foo";
// Act
var name = ApplicationPart.GetResourceNameFromVirtualPath(moduleName, path);
// Assert
Assert.Equal(name, "my-module.program_files.data_files.my file .foo");
}
[Fact]
public void GetResourceVirtualPathForTopLevelItem()
{
// Arrange
var moduleName = "my-module";
var moduleRoot = "~/root-path";
var path = moduleRoot + "/foo.txt";
// Act
var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path);
// Assert
Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + "foo.txt");
}
[Fact]
public void GetResourceVirtualPathForTopLevelItemAndModuleRootWithTrailingSlash()
{
// Arrange
var moduleName = "my-module";
var moduleRoot = "~/root-path/";
var path = moduleRoot + "/foo.txt";
// Act
var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path);
// Assert
Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + "foo.txt");
}
[Fact]
public void GetResourceVirtualPathForTopLevelItemAndNestedModuleRootPath()
{
// Arrange
var moduleName = "my-module";
var moduleRoot = "~/root-path/sub-path";
var path = moduleRoot + "/foo.txt";
// Act
var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path);
// Assert
Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + "foo.txt");
}
[Fact]
public void GetResourceVirtualPathEncodesModuleName()
{
// Arrange
var moduleName = "Debugger Package v?&%";
var moduleRoot = "~/root-path/sub-path";
var path = moduleRoot + "/foo.txt";
// Act
var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path);
// Assert
Assert.Equal(virtualPath, "~/r.ashx/" + "Debugger%20Package%20v?&%" + "/" + "foo.txt");
}
[Fact]
public void GetResourceVirtualPathForNestedItemPath()
{
// Arrange
var moduleName = "DebuggerPackage";
var moduleRoot = "~/root-path/sub-path";
var itemPath = "some-path/some-more-please/foo.txt";
var path = moduleRoot + "/" + itemPath;
// Act
var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path);
// Assert
Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + itemPath);
}
[Fact]
public void GetResourceVirtualPathForItemPathWithParameters()
{
// Arrange
var moduleName = "DebuggerPackage";
var moduleRoot = "~/root-path/sub-path";
var itemPath = "some-path/some-more-please/foo.jpg?size=45&height=20";
var path = moduleRoot + "/" + itemPath;
// Act
var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path);
// Assert
Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + itemPath);
}
}
}

View File

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Internal.Web.Utils;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.WebPages.Test
{
public class MimeMappingTest
{
[Fact]
public void MimeMappingThrowsForNullFileName()
{
// Arrange
string fileName = null;
// Act and Assert
Assert.ThrowsArgumentNull(() => MimeMapping.GetMimeMapping(fileName), "fileName");
}
[Fact]
public void MimeMappingReturnsGenericTypeForUnknownExtensions()
{
// Arrange
string fileName = "file.does-not-exist";
// Act
string mimeType = MimeMapping.GetMimeMapping(fileName);
// Assert
Assert.Equal("application/octet-stream", mimeType);
}
[Fact]
public void MimeMappingReturnsGenericTypeForNoExtensions()
{
// Arrange
string fileName = "file";
// Act
string mimeType = MimeMapping.GetMimeMapping(fileName);
// Assert
Assert.Equal("application/octet-stream", mimeType);
}
[Fact]
public void MimeMappingPerformsCaseInsensitiveSearches()
{
// Arrange
string fileName1 = "file.doc";
string fileName2 = "file.dOC";
// Act
string mimeType1 = MimeMapping.GetMimeMapping(fileName1);
string mimeType2 = MimeMapping.GetMimeMapping(fileName2);
// Assert
Assert.Equal("application/msword", mimeType1);
Assert.Equal("application/msword", mimeType2);
}
}
}

View File

@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.IO;
using System.Text;
using System.Web.WebPages.ApplicationParts;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.WebPages.Test
{
public class ResourceHandlerTest
{
private const string _fileContent = "contents of jpeg file";
[Fact]
public void ResourceHandlerWritesContentsOfFileToStream()
{
// Arrange
var applicationPart = new ApplicationPart(BuildAssembly(), "~/my-app-assembly");
MemoryStream stream = new MemoryStream();
var response = new Mock<HttpResponseBase>();
response.SetupGet(c => c.OutputStream).Returns(stream);
response.SetupSet(c => c.ContentType = "image/jpeg").Verifiable();
var resourceHandler = new ResourceHandler(applicationPart, "bar.foo.jpg");
// Act
resourceHandler.ProcessRequest(response.Object);
// Assert
response.Verify();
Assert.Equal(Encoding.Default.GetString(stream.ToArray()), _fileContent);
}
[Fact]
public void ResourceHandlerThrows404IfResourceNotFound()
{
// Arrange
var applicationPart = new ApplicationPart(BuildAssembly(), "~/my-app-assembly");
MemoryStream stream = new MemoryStream();
var response = new Mock<HttpResponseBase>();
response.SetupGet(c => c.OutputStream).Returns(stream);
response.SetupSet(c => c.ContentType = "image/jpeg").Verifiable();
var resourceHandler = new ResourceHandler(applicationPart, "does-not-exist");
// Act and Assert
Assert.Throws<HttpException>(() => resourceHandler.ProcessRequest(response.Object),
"The resource file \"does-not-exist\" could not be found.");
}
private static IResourceAssembly BuildAssembly(string name = "my-assembly")
{
Mock<TestResourceAssembly> assembly = new Mock<TestResourceAssembly>();
assembly.SetupGet(c => c.Name).Returns("my-assembly");
byte[] content = Encoding.Default.GetBytes(_fileContent);
assembly.Setup(c => c.GetManifestResourceStream("my-assembly.bar.foo.jpg")).Returns(new MemoryStream(content));
assembly.Setup(c => c.GetManifestResourceNames()).Returns(new[] { "my-assembly.bar.foo.jpg" });
return assembly.Object;
}
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Web.WebPages.ApplicationParts;
namespace System.Web.WebPages.Test
{
public abstract class TestResourceAssembly : IResourceAssembly
{
public abstract string Name { get; }
public abstract Stream GetManifestResourceStream(string name);
public abstract IEnumerable<string> GetManifestResourceNames();
public abstract IEnumerable<Type> GetTypes();
}
}

View File

@ -0,0 +1,85 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Web;
using System.Web.WebPages;
using Moq;
using Xunit;
namespace Microsoft.WebPages.Test.Helpers
{
public class HttpContextExtensionsTest
{
class RedirectData
{
public string RequestUrl { get; set; }
public string RedirectUrl { get; set; }
}
private static HttpContextBase GetContextForRedirectLocal(RedirectData data)
{
Mock<HttpContextBase> contextMock = new Mock<HttpContextBase>();
contextMock.Setup(context => context.Request.Url).Returns(new Uri(data.RequestUrl));
contextMock.Setup(context => context.Response.Redirect(It.IsAny<string>())).Callback((string url) => data.RedirectUrl = url);
return contextMock.Object;
}
[Fact]
public void RedirectLocalWithNullGoesToRootTest()
{
RedirectData data = new RedirectData() { RequestUrl = "http://foo" };
var context = GetContextForRedirectLocal(data);
context.RedirectLocal("");
Assert.Equal("~/", data.RedirectUrl);
}
[Fact]
public void RedirectLocalWithEmptyStringGoesToRootTest()
{
RedirectData data = new RedirectData() { RequestUrl = "http://foo" };
var context = GetContextForRedirectLocal(data);
context.RedirectLocal("");
Assert.Equal("~/", data.RedirectUrl);
}
[Fact]
public void RedirectLocalWithNonLocalGoesToRootTest()
{
RedirectData data = new RedirectData() { RequestUrl = "http://foo" };
var context = GetContextForRedirectLocal(data);
context.RedirectLocal("");
Assert.Equal("~/", data.RedirectUrl);
}
[Fact]
public void RedirectLocalWithDifferentHostGoesToRootTest()
{
RedirectData data = new RedirectData() { RequestUrl = "http://foo" };
var context = GetContextForRedirectLocal(data);
context.RedirectLocal("http://bar");
Assert.Equal("~/", data.RedirectUrl);
}
[Fact]
public void RedirectLocalOnSameHostTest()
{
RedirectData data = new RedirectData() { RequestUrl = "http://foo" };
var context = GetContextForRedirectLocal(data);
context.RedirectLocal("http://foo/bar/baz");
Assert.Equal("~/", data.RedirectUrl);
context.RedirectLocal("http://foo/bar/baz/woot.htm");
Assert.Equal("~/", data.RedirectUrl);
}
[Fact]
public void RedirectLocalRelativeTest()
{
RedirectData data = new RedirectData() { RequestUrl = "http://foo" };
var context = GetContextForRedirectLocal(data);
context.RedirectLocal("/bar");
Assert.Equal("/bar", data.RedirectUrl);
context.RedirectLocal("/bar/hey.you");
Assert.Equal("/bar/hey.you", data.RedirectUrl);
}
}
}

View File

@ -0,0 +1,132 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Web;
using System.Web.WebPages;
using Moq;
using Xunit;
namespace Microsoft.WebPages.Test.Helpers
{
public class HttpRequestExtensionsTest
{
private static HttpRequestBase GetRequestForIsUrlLocalToHost(string url)
{
Mock<HttpContextBase> contextMock = new Mock<HttpContextBase>();
contextMock.Setup(context => context.Request.Url).Returns(new Uri(url));
return contextMock.Object.Request;
}
[Fact]
public void IsUrlLocalToHost_ReturnsFalseOnEmpty()
{
var request = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(request.IsUrlLocalToHost(null));
Assert.False(request.IsUrlLocalToHost(String.Empty));
}
[Fact]
public void IsUrlLocalToHost_AcceptsRootedUrls()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.True(helper.IsUrlLocalToHost("/foo.html"));
Assert.True(helper.IsUrlLocalToHost("/www.hackerz.com"));
Assert.True(helper.IsUrlLocalToHost("/"));
}
[Fact]
public void IsUrlLocalToHost_AcceptsApplicationRelativeUrls()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.True(helper.IsUrlLocalToHost("~/"));
Assert.True(helper.IsUrlLocalToHost("~/foobar.html"));
}
[Fact]
public void IsUrlLocalToHost_RejectsRelativeUrls()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("foobar.html"));
Assert.False(helper.IsUrlLocalToHost("../foobar.html"));
Assert.False(helper.IsUrlLocalToHost("fold/foobar.html"));
}
[Fact]
public void IsUrlLocalToHost_RejectValidButUnsafeRelativeUrls()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("http:/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("hTtP:foobar.html"));
Assert.False(helper.IsUrlLocalToHost("http:/www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost("HtTpS:/www.hackerz.com"));
}
[Fact]
public void IsUrlLocalToHost_RejectsUrlsOnTheSameHost()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("http://www.mysite.com/appDir/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("http://WWW.MYSITE.COM"));
}
[Fact]
public void IsUrlLocalToHost_RejectsUrlsOnLocalHost()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("http://localhost/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("http://127.0.0.1/foobar.html"));
}
[Fact]
public void IsUrlLocalToHost_RejectsUrlsOnTheSameHostButDifferentScheme()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("https://www.mysite.com/"));
}
[Fact]
public void IsUrlLocalToHost_RejectsUrlsOnDifferentHost()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("http://www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost("https://www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost("hTtP://www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost("HtTpS://www.hackerz.com"));
}
[Fact]
public void IsUrlLocalToHost_RejectsUrlsWithTooManySchemeSeparatorCharacters()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("http://///www.hackerz.com/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("https://///www.hackerz.com/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("HtTpS://///www.hackerz.com/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("http:///www.hackerz.com/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("http:////www.hackerz.com/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("http://///www.hackerz.com/foobar.html"));
}
[Fact]
public void IsUrlLocalToHost_RejectsUrlsWithMissingSchemeName()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost("//www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost("//www.hackerz.com?"));
Assert.False(helper.IsUrlLocalToHost("//www.hackerz.com:80"));
Assert.False(helper.IsUrlLocalToHost("//www.hackerz.com/foobar.html"));
Assert.False(helper.IsUrlLocalToHost("///www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost("//////www.hackerz.com"));
}
[Fact]
public void IsUrlLocalToHost_RejectsInvalidUrls()
{
var helper = GetRequestForIsUrlLocalToHost("http://www.mysite.com/");
Assert.False(helper.IsUrlLocalToHost(@"http:\\www.hackerz.com"));
Assert.False(helper.IsUrlLocalToHost(@"http:\\www.hackerz.com\"));
Assert.False(helper.IsUrlLocalToHost(@"/\"));
Assert.False(helper.IsUrlLocalToHost(@"/\foo"));
}
}
}

View File

@ -0,0 +1,130 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.WebPages;
using Moq;
using Xunit;
namespace Microsoft.WebPages.Test.Helpers
{
public class HttpResponseExtensionsTest
{
HttpResponseBase _response;
string _redirectUrl;
StringBuilder _output;
Stream _outputStream;
public HttpResponseExtensionsTest()
{
_output = new StringBuilder();
_outputStream = new MemoryStream();
Mock<HttpResponseBase> mockResponse = new Mock<HttpResponseBase>();
mockResponse.SetupProperty(response => response.StatusCode);
mockResponse.SetupProperty(response => response.ContentType);
mockResponse.Setup(response => response.Redirect(It.IsAny<string>())).Callback((string url) => _redirectUrl = url);
mockResponse.Setup(response => response.Write(It.IsAny<string>())).Callback((string str) => _output.Append(str));
mockResponse.Setup(response => response.OutputStream).Returns(_outputStream);
mockResponse.Setup(response => response.OutputStream).Returns(_outputStream);
mockResponse.Setup(response => response.Output).Returns(new StringWriter(_output));
_response = mockResponse.Object;
}
[Fact]
public void SetStatusWithIntTest()
{
int status = 200;
_response.SetStatus(status);
Assert.Equal(status, _response.StatusCode);
}
[Fact]
public void SetStatusWithHttpStatusCodeTest()
{
HttpStatusCode status = HttpStatusCode.Forbidden;
_response.SetStatus(status);
Assert.Equal((int)status, _response.StatusCode);
}
[Fact]
public void WriteBinaryTest()
{
string foo = "I am a string, please don't mangle me!";
_response.WriteBinary(ASCIIEncoding.ASCII.GetBytes(foo));
_outputStream.Flush();
_outputStream.Position = 0;
StreamReader reader = new StreamReader(_outputStream);
Assert.Equal(foo, reader.ReadToEnd());
}
[Fact]
public void WriteBinaryWithMimeTypeTest()
{
string foo = "I am a string, please don't mangle me!";
string mimeType = "mime/foo";
_response.WriteBinary(ASCIIEncoding.ASCII.GetBytes(foo), mimeType);
_outputStream.Flush();
_outputStream.Position = 0;
StreamReader reader = new StreamReader(_outputStream);
Assert.Equal(foo, reader.ReadToEnd());
Assert.Equal(mimeType, _response.ContentType);
}
[Fact]
public void OutputCacheSetsExpirationTimeBasedOnCurrentContext()
{
// Arrange
var timestamp = new DateTime(2011, 1, 1, 0, 0, 0);
var context = new Mock<HttpContextBase>();
context.SetupGet(c => c.Timestamp).Returns(timestamp);
var response = new Mock<HttpResponseBase>().Object;
var cache = new Mock<HttpCachePolicyBase>();
cache.Setup(c => c.SetCacheability(It.Is<HttpCacheability>(p => p == HttpCacheability.Public))).Verifiable();
cache.Setup(c => c.SetExpires(It.Is<DateTime>(p => p == timestamp.AddSeconds(20)))).Verifiable();
cache.Setup(c => c.SetMaxAge(It.Is<TimeSpan>(p => p == TimeSpan.FromSeconds(20)))).Verifiable();
cache.Setup(c => c.SetValidUntilExpires(It.Is<bool>(p => p == true))).Verifiable();
cache.Setup(c => c.SetLastModified(It.Is<DateTime>(p => p == timestamp))).Verifiable();
cache.Setup(c => c.SetSlidingExpiration(It.Is<bool>(p => p == false))).Verifiable();
// Act
ResponseExtensions.OutputCache(context.Object, cache.Object, 20, false, null, null, null, HttpCacheability.Public);
// Assert
cache.VerifyAll();
}
[Fact]
public void OutputCacheSetsVaryByValues()
{
// Arrange
var timestamp = new DateTime(2011, 1, 1, 0, 0, 0);
var context = new Mock<HttpContextBase>();
context.SetupGet(c => c.Timestamp).Returns(timestamp);
var response = new Mock<HttpResponseBase>().Object;
var varyByParams = new HttpCacheVaryByParams();
var varyByHeader = new HttpCacheVaryByHeaders();
var varyByContentEncoding = new HttpCacheVaryByContentEncodings();
var cache = new Mock<HttpCachePolicyBase>();
cache.SetupGet(c => c.VaryByParams).Returns(varyByParams);
cache.SetupGet(c => c.VaryByHeaders).Returns(varyByHeader);
cache.SetupGet(c => c.VaryByContentEncodings).Returns(varyByContentEncoding);
// Act
ResponseExtensions.OutputCache(context.Object, cache.Object, 20, false, new[] { "foo" }, new[] { "bar", "bar2" },
new[] { "baz", "baz2" }, HttpCacheability.Public);
// Assert
Assert.Equal(varyByParams["foo"], true);
Assert.Equal(varyByHeader["bar"], true);
Assert.Equal(varyByHeader["bar2"], true);
Assert.Equal(varyByContentEncoding["baz"], true);
Assert.Equal(varyByContentEncoding["baz2"], true);
}
}
}

View File

@ -0,0 +1,253 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Globalization;
using System.Web.TestUtil;
using Xunit;
using Xunit.Extensions;
namespace System.Web.WebPages.Test
{
public class StringExtensionsTest
{
[Fact]
public void IsIntTests()
{
Assert.False("1.3".IsInt());
Assert.False(".13".IsInt());
Assert.False("0.0".IsInt());
Assert.False("12345678900123456".IsInt());
Assert.False("gooblygook".IsInt());
Assert.True("0".IsInt());
Assert.True("123456".IsInt());
Assert.True(Int32.MaxValue.ToString().IsInt());
Assert.True(Int32.MinValue.ToString().IsInt());
Assert.False(((string)null).IsInt());
}
[Fact]
public void AsIntBasicTests()
{
Assert.Equal(-123, "-123".AsInt());
Assert.Equal(12345, "12345".AsInt());
Assert.Equal(0, "0".AsInt());
}
[Fact]
public void AsIntDefaultTests()
{
// Illegal values default to 0
Assert.Equal(0, "-100000000000000000000000".AsInt());
// Illegal values default to 0
Assert.Equal(0, "adlfkj".AsInt());
Assert.Equal(-1, "adlfkj".AsInt(-1));
Assert.Equal(-1, "-100000000000000000000000".AsInt(-1));
}
[Fact]
public void IsDecimalTests()
{
Assert.True("1.3".IsDecimal());
Assert.True(".13".IsDecimal());
Assert.True("0.0".IsDecimal());
Assert.True("12345678900123456".IsDecimal());
Assert.True("0".IsDecimal());
Assert.True("123456".IsDecimal());
Assert.True(decimal.MaxValue.ToString().IsDecimal());
Assert.True(decimal.MinValue.ToString().IsDecimal());
Assert.False("gooblygook".IsDecimal());
Assert.False("..0".IsDecimal());
Assert.False(((string)null).IsDecimal());
}
[Fact]
public void AsDecimalBasicTests()
{
Assert.Equal(-123m, "-123".AsDecimal());
Assert.Equal(9.99m, "9.99".AsDecimal());
Assert.Equal(0m, "0".AsDecimal());
Assert.Equal(-1.1111m, "-1.1111".AsDecimal());
}
[Fact]
public void AsDecimalDefaultTests()
{
// Illegal values default to 0
Assert.Equal(0m, "abc".AsDecimal());
Assert.Equal(-1.11m, "adlfkj".AsDecimal(-1.11m));
}
[Fact]
public void AsDecimalUsesCurrentCulture()
{
decimal value = 12345.00M;
using (new CultureReplacer("ar-DZ"))
{
Assert.Equal(value.ToString(CultureInfo.CurrentCulture), "12345.00");
Assert.Equal(value.ToString(), "12345.00");
}
using (new CultureReplacer("bg-BG"))
{
Assert.Equal(value.ToString(CultureInfo.CurrentCulture), "12345,00");
Assert.Equal(value.ToString(), "12345,00");
}
}
[Fact]
public void IsAndAsDecimalsUsesCurrentCulture()
{
// Pretty identical to the earlier test case. This was a post on the forums, making sure it works.
using (new CultureReplacer(culture: "lt-LT"))
{
Assert.False("1.2".IsDecimal());
Assert.True("1,2".IsDecimal());
Assert.Equal(1.2M, "1,2".AsDecimal());
Assert.Equal(0, "1.2".AsDecimal());
}
}
[Fact]
public void IsFloatTests()
{
Assert.True("1.3".IsFloat());
Assert.True(".13".IsFloat());
Assert.True("0.0".IsFloat());
Assert.True("12345678900123456".IsFloat());
Assert.True("0".IsFloat());
Assert.True("123456".IsFloat());
Assert.True(float.MaxValue.ToString().IsFloat());
Assert.True(float.MinValue.ToString().IsFloat());
Assert.True(float.NegativeInfinity.ToString().IsFloat());
Assert.True(float.PositiveInfinity.ToString().IsFloat());
Assert.False("gooblygook".IsFloat());
Assert.False(((string)null).IsFloat());
}
[Fact]
public void AsFloatBasicTests()
{
Assert.Equal(-123f, "-123".AsFloat());
Assert.Equal(9.99f, "9.99".AsFloat());
Assert.Equal(0f, "0".AsFloat());
Assert.Equal(-1.1111f, "-1.1111".AsFloat());
}
[Fact]
public void AsFloatDefaultTests()
{
// Illegal values default to 0
Assert.Equal(0f, "abc".AsFloat());
Assert.Equal(-1.11f, "adlfkj".AsFloat(-1.11f));
}
[Fact]
public void IsDateTimeTests()
{
using (new CultureReplacer())
{
Assert.True("Sat, 01 Nov 2008 19:35:00 GMT".IsDateTime());
Assert.True("1/5/1979".IsDateTime());
Assert.False("0".IsDateTime());
Assert.True(DateTime.MaxValue.ToString().IsDateTime());
Assert.True(DateTime.MinValue.ToString().IsDateTime());
Assert.True(new DateTime(2010, 12, 21).ToUniversalTime().ToString().IsDateTime());
Assert.False("gooblygook".IsDateTime());
Assert.False(((string)null).IsDateTime());
}
}
/// <remarks>Tests for bug 153439</remarks>
[Fact]
public void IsDateTimeUsesLocalCulture()
{
using (new CultureReplacer(culture: "en-gb"))
{
Assert.True(new DateTime(2010, 12, 21).ToString().IsDateTime());
Assert.True(new DateTime(2010, 12, 11).ToString().IsDateTime());
Assert.True("2010/01/01".IsDateTime());
Assert.True("12/01/2010".IsDateTime());
Assert.True("12/12/2010".IsDateTime());
Assert.True("13/12/2010".IsDateTime());
Assert.True("2010-12-01".IsDateTime());
Assert.True("2010-12-13".IsDateTime());
Assert.False("12/13/2010".IsDateTime());
Assert.False("13/13/2010".IsDateTime());
Assert.False("2010-13-12".IsDateTime());
}
}
[Fact]
public void AsDateTimeBasicTests()
{
using (new CultureReplacer())
{
Assert.Equal(DateTime.Parse("1/14/1979"), "1/14/1979".AsDateTime());
Assert.Equal(DateTime.Parse("Sat, 01 Nov 2008 19:35:00 GMT"), "Sat, 01 Nov 2008 19:35:00 GMT".AsDateTime());
}
}
[Theory]
[InlineData(new object[] { "en-us" })]
[InlineData(new object[] { "en-gb" })]
[InlineData(new object[] { "ug" })]
[InlineData(new object[] { "lt-LT" })]
public void AsDateTimeDefaultTests(string culture)
{
using (new CultureReplacer(culture))
{
// Illegal values default to MinTime
Assert.Equal(DateTime.MinValue, "1".AsDateTime());
DateTime defaultV = new DateTime(1979, 01, 05);
Assert.Equal(defaultV, "adlfkj".AsDateTime(defaultV));
Assert.Equal(defaultV, "Jn 69".AsDateTime(defaultV));
}
}
[Theory]
[InlineData(new object[] { "en-us" })]
[InlineData(new object[] { "en-gb" })]
[InlineData(new object[] { "lt-LT" })]
public void IsDateTimeDefaultTests(string culture)
{
using (new CultureReplacer(culture))
{
var dateTime = new DateTime(2011, 10, 25, 10, 10, 00);
Assert.True(dateTime.ToShortDateString().IsDateTime());
Assert.True(dateTime.ToString().IsDateTime());
Assert.True(dateTime.ToLongDateString().IsDateTime());
}
}
[Fact]
public void IsBoolTests()
{
Assert.True("TRUE".IsBool());
Assert.True("TRUE ".IsBool());
Assert.True("false".IsBool());
Assert.False("falsey".IsBool());
Assert.False("gooblygook".IsBool());
Assert.False("".IsBool());
Assert.False(((string)null).IsBool());
}
[Fact]
public void AsBoolTests()
{
Assert.True("TRuE".AsBool());
Assert.False("False".AsBool());
Assert.False("Die".AsBool(false));
Assert.True("true!".AsBool(true));
Assert.False("".AsBool());
Assert.False(((string)null).AsBool());
Assert.True("".AsBool(true));
Assert.True(((string)null).AsBool(true));
}
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.Test
{
public class AntiForgeryConfigTest
{
[Theory]
[InlineData(null, "__RequestVerificationToken")]
[InlineData("", "__RequestVerificationToken")]
[InlineData("/", "__RequestVerificationToken")]
[InlineData("/path", "__RequestVerificationToken_L3BhdGg1")]
public void GetAntiForgeryCookieName(string appPath, string expectedCookieName)
{
// Act
string retVal = AntiForgeryConfig.GetAntiForgeryCookieName(appPath);
// Assert
Assert.Equal(expectedCookieName, retVal);
}
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.Test
{
public class AntiForgeryTest
{
[Fact]
public void GetHtml_ThrowsWhenNotCalledInWebContext()
{
Assert.Throws<ArgumentException>(() => AntiForgery.GetHtml(),
"An HttpContext is required to perform this operation. Check that this operation is being performed during a web request.");
}
[Fact]
public void GetTokens_ThrowsWhenNotCalledInWebContext()
{
Assert.Throws<ArgumentException>(() => { string dummy1, dummy2; AntiForgery.GetTokens("dummy", out dummy1, out dummy2); },
"An HttpContext is required to perform this operation. Check that this operation is being performed during a web request.");
}
[Fact]
public void Validate_ThrowsWhenNotCalledInWebContext()
{
Assert.Throws<ArgumentException>(() => AntiForgery.Validate(),
"An HttpContext is required to perform this operation. Check that this operation is being performed during a web request.");
Assert.Throws<ArgumentException>(() => AntiForgery.Validate("cookie-token", "form-token"),
"An HttpContext is required to perform this operation. Check that this operation is being performed during a web request.");
}
}
}

View File

@ -0,0 +1,178 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web.Mvc;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class AntiForgeryTokenSerializerTest
{
private static readonly AntiForgeryTokenSerializer _testSerializer = new AntiForgeryTokenSerializer(cryptoSystem: CreateIdentityTransformCryptoSystem());
private static readonly BinaryBlob _claimUid = new BinaryBlob(256, new byte[] { 0x6F, 0x16, 0x48, 0xE9, 0x72, 0x49, 0xAA, 0x58, 0x75, 0x40, 0x36, 0xA6, 0x7E, 0x24, 0x8C, 0xF0, 0x44, 0xF0, 0x7E, 0xCF, 0xB0, 0xED, 0x38, 0x75, 0x56, 0xCE, 0x02, 0x9A, 0x4F, 0x9A, 0x40, 0xE0 });
private static readonly BinaryBlob _securityToken = new BinaryBlob(128, new byte[] { 0x70, 0x5E, 0xED, 0xCC, 0x7D, 0x42, 0xF1, 0xD6, 0xB3, 0xB9, 0x8A, 0x59, 0x36, 0x25, 0xBB, 0x4C });
[Theory]
[InlineData(
"01" // Version
+ "705EEDCC7D42F1D6B3B9" // SecurityToken
// (WRONG!) Stream ends too early
)]
[InlineData(
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "01" // IsSessionToken
+ "00" // (WRONG!) Too much data in stream
)]
[InlineData(
"02" // (WRONG! - must be 0x01) Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "01" // IsSessionToken
)]
[InlineData(
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "00" // IsSessionToken
+ "00" // IsClaimsBased
+ "05" // Username length header
+ "0000" // (WRONG!) Too little data in stream
)]
public void Deserialize_BadToken(string serializedToken)
{
// Act & assert
var ex = Assert.Throws<HttpAntiForgeryException>(() => _testSerializer.Deserialize(serializedToken));
Assert.Equal(@"The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the <machineKey> configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.", ex.Message);
}
[Fact]
public void Serialize_FieldToken_WithClaimUid()
{
// Arrange
const string expectedSerializedData =
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "00" // IsSessionToken
+ "01" // IsClaimsBased
+ "6F1648E97249AA58754036A67E248CF044F07ECFB0ED387556CE029A4F9A40E0" // ClaimUid
+ "05" // AdditionalData length header
+ "E282AC3437"; // AdditionalData ("€47") as UTF8
AntiForgeryToken token = new AntiForgeryToken()
{
SecurityToken = _securityToken,
IsSessionToken = false,
ClaimUid = _claimUid,
AdditionalData = "€47"
};
// Act & assert - serialization
string actualSerializedData = _testSerializer.Serialize(token);
Assert.Equal(expectedSerializedData, actualSerializedData);
// Act & assert - deserialization
AntiForgeryToken deserializedToken = _testSerializer.Deserialize(actualSerializedData);
AssertTokensEqual(token, deserializedToken);
}
[Fact]
public void Serialize_FieldToken_WithUsername()
{
// Arrange
const string expectedSerializedData =
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "00" // IsSessionToken
+ "00" // IsClaimsBased
+ "08" // Username length header
+ "4AC3A972C3B46D65" // Username ("Jérôme") as UTF8
+ "05" // AdditionalData length header
+ "E282AC3437"; // AdditionalData ("€47") as UTF8
AntiForgeryToken token = new AntiForgeryToken()
{
SecurityToken = _securityToken,
IsSessionToken = false,
Username = "Jérôme",
AdditionalData = "€47"
};
// Act & assert - serialization
string actualSerializedData = _testSerializer.Serialize(token);
Assert.Equal(expectedSerializedData, actualSerializedData);
// Act & assert - deserialization
AntiForgeryToken deserializedToken = _testSerializer.Deserialize(actualSerializedData);
AssertTokensEqual(token, deserializedToken);
}
[Fact]
public void Serialize_SessionToken()
{
// Arrange
const string expectedSerializedData =
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "01"; // IsSessionToken
AntiForgeryToken token = new AntiForgeryToken()
{
SecurityToken = _securityToken,
IsSessionToken = true
};
// Act & assert - serialization
string actualSerializedData = _testSerializer.Serialize(token);
Assert.Equal(expectedSerializedData, actualSerializedData);
// Act & assert - deserialization
AntiForgeryToken deserializedToken = _testSerializer.Deserialize(actualSerializedData);
AssertTokensEqual(token, deserializedToken);
}
private static string BytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}", b);
}
return sb.ToString();
}
private static byte[] HexToBytes(string hex)
{
List<byte> bytes = new List<byte>();
for (int i = 0; i < hex.Length; i += 2)
{
byte b = Byte.Parse(hex.Substring(i, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
bytes.Add(b);
}
return bytes.ToArray();
}
private static ICryptoSystem CreateIdentityTransformCryptoSystem()
{
Mock<MockableCryptoSystem> mockCryptoSystem = new Mock<MockableCryptoSystem>();
mockCryptoSystem.Setup(o => o.Protect(It.IsAny<byte[]>())).Returns<byte[]>(HexUtil.HexEncode);
mockCryptoSystem.Setup(o => o.Unprotect(It.IsAny<string>())).Returns<string>(HexUtil.HexDecode);
return mockCryptoSystem.Object;
}
private static void AssertTokensEqual(AntiForgeryToken expected, AntiForgeryToken actual)
{
Assert.NotNull(expected);
Assert.NotNull(actual);
Assert.Equal(expected.AdditionalData, actual.AdditionalData);
Assert.Equal(expected.ClaimUid, actual.ClaimUid);
Assert.Equal(expected.IsSessionToken, actual.IsSessionToken);
Assert.Equal(expected.SecurityToken, actual.SecurityToken);
Assert.Equal(expected.Username, actual.Username);
}
}
}

View File

@ -0,0 +1,236 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Mvc;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class AntiForgeryTokenStoreTest
{
[Fact]
public void GetCookieToken_CookieDoesNotExist_ReturnsNull()
{
// Arrange
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Cookies).Returns(new HttpCookieCollection());
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
CookieName = "cookie-name"
};
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: null);
// Act
AntiForgeryToken token = tokenStore.GetCookieToken(mockHttpContext.Object);
// Assert
Assert.Null(token);
}
[Fact]
public void GetCookieToken_CookieIsEmpty_ReturnsNull()
{
// Arrange
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Cookies).Returns(new HttpCookieCollection()
{
new HttpCookie("cookie-name", "")
});
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
CookieName = "cookie-name"
};
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: null);
// Act
AntiForgeryToken token = tokenStore.GetCookieToken(mockHttpContext.Object);
// Assert
Assert.Null(token);
}
[Fact]
public void GetCookieToken_CookieIsInvalid_PropagatesException()
{
// Arrange
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Cookies).Returns(new HttpCookieCollection()
{
new HttpCookie("cookie-name", "invalid-value")
});
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
CookieName = "cookie-name"
};
HttpAntiForgeryException expectedException = new HttpAntiForgeryException("some exception");
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Deserialize("invalid-value")).Throws(expectedException);
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: mockSerializer.Object);
// Act & assert
var ex = Assert.Throws<HttpAntiForgeryException>(() => tokenStore.GetCookieToken(mockHttpContext.Object));
Assert.Equal(expectedException, ex);
}
[Fact]
public void GetCookieToken_CookieIsValid_ReturnsToken()
{
// Arrange
AntiForgeryToken expectedToken = new AntiForgeryToken();
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Cookies).Returns(new HttpCookieCollection()
{
new HttpCookie("cookie-name", "valid-value")
});
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
CookieName = "cookie-name"
};
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Deserialize("valid-value")).Returns((object)expectedToken);
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: mockSerializer.Object);
// Act
AntiForgeryToken retVal = tokenStore.GetCookieToken(mockHttpContext.Object);
// Assert
Assert.Same(expectedToken, retVal);
}
[Fact]
public void GetFormToken_FormFieldIsEmpty_ReturnsNull()
{
// Arrange
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Form.Get("form-field-name")).Returns("");
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
FormFieldName = "form-field-name"
};
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: null);
// Act
AntiForgeryToken token = tokenStore.GetFormToken(mockHttpContext.Object);
// Assert
Assert.Null(token);
}
[Fact]
public void GetFormToken_FormFieldIsInvalid_PropagatesException()
{
// Arrange
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Form.Get("form-field-name")).Returns("invalid-value");
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
FormFieldName = "form-field-name"
};
HttpAntiForgeryException expectedException = new HttpAntiForgeryException("some exception");
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Deserialize("invalid-value")).Throws(expectedException);
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: mockSerializer.Object);
// Act & assert
var ex = Assert.Throws<HttpAntiForgeryException>(() => tokenStore.GetFormToken(mockHttpContext.Object));
Assert.Same(expectedException, ex);
}
[Fact]
public void GetFormToken_FormFieldIsValid_ReturnsToken()
{
// Arrange
AntiForgeryToken expectedToken = new AntiForgeryToken();
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.Form.Get("form-field-name")).Returns("valid-value");
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
FormFieldName = "form-field-name"
};
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Deserialize("valid-value")).Returns((object)expectedToken);
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: mockSerializer.Object);
// Act
AntiForgeryToken retVal = tokenStore.GetFormToken(mockHttpContext.Object);
// Assert
Assert.Same(expectedToken, retVal);
}
[Theory]
[InlineData(true, true)]
[InlineData(false, null)]
public void SaveCookieToken(bool requireSsl, bool? expectedCookieSecureFlag)
{
// Arrange
AntiForgeryToken token = new AntiForgeryToken();
HttpCookieCollection cookies = new HttpCookieCollection();
bool defaultCookieSecureValue = expectedCookieSecureFlag ?? new HttpCookie("name", "value").Secure; // pulled from config; set by ctor
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Response.Cookies).Returns(cookies);
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Serialize(token)).Returns("serialized-value");
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
CookieName = "cookie-name",
RequireSSL = requireSsl
};
AntiForgeryTokenStore tokenStore = new AntiForgeryTokenStore(
config: config,
serializer: mockSerializer.Object);
// Act
tokenStore.SaveCookieToken(mockHttpContext.Object, token);
// Assert
Assert.Equal(1, cookies.Count);
HttpCookie cookie = cookies["cookie-name"];
Assert.NotNull(cookie);
Assert.Equal("serialized-value", cookie.Value);
Assert.True(cookie.HttpOnly);
Assert.Equal(defaultCookieSecureValue, cookie.Secure);
}
}
}

View File

@ -0,0 +1,108 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class AntiForgeryTokenTest
{
[Fact]
public void AdditionalDataProperty()
{
// Arrange
AntiForgeryToken token = new AntiForgeryToken();
// Act & assert - 1
Assert.Equal("", token.AdditionalData);
// Act & assert - 2
token.AdditionalData = "additional data";
Assert.Equal("additional data", token.AdditionalData);
// Act & assert - 3
token.AdditionalData = null;
Assert.Equal("", token.AdditionalData);
}
[Fact]
public void ClaimUidProperty()
{
// Arrange
AntiForgeryToken token = new AntiForgeryToken();
// Act & assert - 1
Assert.Null(token.ClaimUid);
// Act & assert - 2
BinaryBlob blob = new BinaryBlob(32);
token.ClaimUid = blob;
Assert.Equal(blob, token.ClaimUid);
// Act & assert - 3
token.ClaimUid = null;
Assert.Null(token.ClaimUid);
}
[Fact]
public void IsSessionTokenProperty()
{
// Arrange
AntiForgeryToken token = new AntiForgeryToken();
// Act & assert - 1
Assert.False(token.IsSessionToken);
// Act & assert - 2
token.IsSessionToken = true;
Assert.True(token.IsSessionToken);
// Act & assert - 3
token.IsSessionToken = false;
Assert.False(token.IsSessionToken);
}
[Fact]
public void SecurityTokenProperty()
{
// Arrange
AntiForgeryToken token = new AntiForgeryToken();
// Act & assert - 1
BinaryBlob securityToken = token.SecurityToken;
Assert.NotNull(securityToken);
Assert.Equal(AntiForgeryToken.SecurityTokenBitLength, securityToken.BitLength);
Assert.Equal(securityToken, token.SecurityToken); // check that we're not making a new one each property call
// Act & assert - 2
securityToken = new BinaryBlob(64);
token.SecurityToken = securityToken;
Assert.Equal(securityToken, token.SecurityToken);
// Act & assert - 3
token.SecurityToken = null;
securityToken = token.SecurityToken;
Assert.NotNull(securityToken);
Assert.Equal(AntiForgeryToken.SecurityTokenBitLength, securityToken.BitLength);
Assert.Equal(securityToken, token.SecurityToken); // check that we're not making a new one each property call
}
[Fact]
public void UsernameProperty()
{
// Arrange
AntiForgeryToken token = new AntiForgeryToken();
// Act & assert - 1
Assert.Equal("", token.Username);
// Act & assert - 2
token.Username = "my username";
Assert.Equal("my username", token.Username);
// Act & assert - 3
token.Username = null;
Assert.Equal("", token.Username);
}
}
}

View File

@ -0,0 +1,403 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Security.Principal;
using System.Web.Helpers.Test;
using System.Web.Mvc;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class AntiForgeryWorkerTest
{
[Fact]
public void ChecksSSL()
{
// Arrange
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.Request.IsSecureConnection).Returns(false);
IAntiForgeryConfig config = new MockAntiForgeryConfig()
{
RequireSSL = true
};
AntiForgeryWorker worker = new AntiForgeryWorker(
config: config,
serializer: null,
tokenStore: null,
validator: null);
// Act & assert
var ex = Assert.Throws<InvalidOperationException>(() => worker.Validate(mockHttpContext.Object, "session-token", "field-token"));
Assert.Equal(@"The anti-forgery system has the configuration value AntiForgeryConfig.RequireSsl = true, but the current request is not an SSL request.", ex.Message);
ex = Assert.Throws<InvalidOperationException>(() => worker.Validate(mockHttpContext.Object));
Assert.Equal(@"The anti-forgery system has the configuration value AntiForgeryConfig.RequireSsl = true, but the current request is not an SSL request.", ex.Message);
ex = Assert.Throws<InvalidOperationException>(() => worker.GetFormInputElement(mockHttpContext.Object));
Assert.Equal(@"The anti-forgery system has the configuration value AntiForgeryConfig.RequireSsl = true, but the current request is not an SSL request.", ex.Message);
ex = Assert.Throws<InvalidOperationException>(() => { string dummy1, dummy2; worker.GetTokens(mockHttpContext.Object, "cookie-token", out dummy1, out dummy2); });
Assert.Equal(@"The anti-forgery system has the configuration value AntiForgeryConfig.RequireSsl = true, but the current request is not an SSL request.", ex.Message);
}
[Fact]
public void GetFormInputElement_ExistingInvalidCookieToken()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken oldCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken newCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken formToken = new AntiForgeryToken();
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
FormFieldName = "form-field-name"
};
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>(MockBehavior.Strict);
mockSerializer.Setup(o => o.Serialize(formToken)).Returns("serialized-form-token");
Mock<MockableTokenStore> mockTokenStore = new Mock<MockableTokenStore>(MockBehavior.Strict);
mockTokenStore.Setup(o => o.GetCookieToken(mockHttpContext.Object)).Returns(oldCookieToken);
mockTokenStore.Setup(o => o.SaveCookieToken(mockHttpContext.Object, newCookieToken)).Verifiable();
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>(MockBehavior.Strict);
mockValidator.Setup(o => o.GenerateFormToken(mockHttpContext.Object, identity, newCookieToken)).Returns(formToken);
mockValidator.Setup(o => o.IsCookieTokenValid(oldCookieToken)).Returns(false);
mockValidator.Setup(o => o.IsCookieTokenValid(newCookieToken)).Returns(true);
mockValidator.Setup(o => o.GenerateCookieToken()).Returns(newCookieToken);
AntiForgeryWorker worker = new AntiForgeryWorker(
config: config,
serializer: mockSerializer.Object,
tokenStore: mockTokenStore.Object,
validator: mockValidator.Object);
// Act
TagBuilder retVal = worker.GetFormInputElement(mockHttpContext.Object);
// Assert
Assert.Equal(@"<input name=""form-field-name"" type=""hidden"" value=""serialized-form-token"" />", retVal.ToString(TagRenderMode.SelfClosing));
mockTokenStore.Verify();
}
[Fact]
public void GetFormInputElement_ExistingInvalidCookieToken_SwallowsExceptions()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken oldCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken newCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken formToken = new AntiForgeryToken();
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
FormFieldName = "form-field-name"
};
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>(MockBehavior.Strict);
mockSerializer.Setup(o => o.Serialize(formToken)).Returns("serialized-form-token");
Mock<MockableTokenStore> mockTokenStore = new Mock<MockableTokenStore>(MockBehavior.Strict);
mockTokenStore.Setup(o => o.GetCookieToken(mockHttpContext.Object)).Throws(new Exception("should be swallowed"));
mockTokenStore.Setup(o => o.SaveCookieToken(mockHttpContext.Object, newCookieToken)).Verifiable();
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>(MockBehavior.Strict);
mockValidator.Setup(o => o.GenerateFormToken(mockHttpContext.Object, identity, newCookieToken)).Returns(formToken);
mockValidator.Setup(o => o.IsCookieTokenValid(null)).Returns(false);
mockValidator.Setup(o => o.IsCookieTokenValid(newCookieToken)).Returns(true);
mockValidator.Setup(o => o.GenerateCookieToken()).Returns(newCookieToken);
AntiForgeryWorker worker = new AntiForgeryWorker(
config: config,
serializer: mockSerializer.Object,
tokenStore: mockTokenStore.Object,
validator: mockValidator.Object);
// Act
TagBuilder retVal = worker.GetFormInputElement(mockHttpContext.Object);
// Assert
Assert.Equal(@"<input name=""form-field-name"" type=""hidden"" value=""serialized-form-token"" />", retVal.ToString(TagRenderMode.SelfClosing));
mockTokenStore.Verify();
}
[Fact]
public void GetFormInputElement_ExistingValidCookieToken()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken cookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken formToken = new AntiForgeryToken();
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
FormFieldName = "form-field-name"
};
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>(MockBehavior.Strict);
mockSerializer.Setup(o => o.Serialize(formToken)).Returns("serialized-form-token");
Mock<MockableTokenStore> mockTokenStore = new Mock<MockableTokenStore>(MockBehavior.Strict);
mockTokenStore.Setup(o => o.GetCookieToken(mockHttpContext.Object)).Returns(cookieToken);
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>(MockBehavior.Strict);
mockValidator.Setup(o => o.GenerateFormToken(mockHttpContext.Object, identity, cookieToken)).Returns(formToken);
mockValidator.Setup(o => o.IsCookieTokenValid(cookieToken)).Returns(true);
AntiForgeryWorker worker = new AntiForgeryWorker(
config: config,
serializer: mockSerializer.Object,
tokenStore: mockTokenStore.Object,
validator: mockValidator.Object);
// Act
TagBuilder retVal = worker.GetFormInputElement(mockHttpContext.Object);
// Assert
Assert.Equal(@"<input name=""form-field-name"" type=""hidden"" value=""serialized-form-token"" />", retVal.ToString(TagRenderMode.SelfClosing));
}
[Fact]
public void GetTokens_ExistingInvalidCookieToken()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken oldCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken newCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>(MockBehavior.Strict);
mockSerializer.Setup(o => o.Deserialize("serialized-old-cookie-token")).Returns(oldCookieToken);
mockSerializer.Setup(o => o.Serialize(newCookieToken)).Returns("serialized-new-cookie-token");
mockSerializer.Setup(o => o.Serialize(formToken)).Returns("serialized-form-token");
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>(MockBehavior.Strict);
mockValidator.Setup(o => o.GenerateFormToken(mockHttpContext.Object, identity, newCookieToken)).Returns(formToken);
mockValidator.Setup(o => o.IsCookieTokenValid(oldCookieToken)).Returns(false);
mockValidator.Setup(o => o.IsCookieTokenValid(newCookieToken)).Returns(true);
mockValidator.Setup(o => o.GenerateCookieToken()).Returns(newCookieToken);
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: mockSerializer.Object,
tokenStore: null,
validator: mockValidator.Object);
// Act
string serializedNewCookieToken, serializedFormToken;
worker.GetTokens(mockHttpContext.Object, "serialized-old-cookie-token", out serializedNewCookieToken, out serializedFormToken);
// Assert
Assert.Equal("serialized-new-cookie-token", serializedNewCookieToken);
Assert.Equal("serialized-form-token", serializedFormToken);
}
[Fact]
public void GetTokens_ExistingInvalidCookieToken_SwallowsExceptions()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken oldCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken newCookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>(MockBehavior.Strict);
mockSerializer.Setup(o => o.Deserialize("serialized-old-cookie-token")).Throws(new Exception("should be swallowed"));
mockSerializer.Setup(o => o.Serialize(newCookieToken)).Returns("serialized-new-cookie-token");
mockSerializer.Setup(o => o.Serialize(formToken)).Returns("serialized-form-token");
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>(MockBehavior.Strict);
mockValidator.Setup(o => o.GenerateFormToken(mockHttpContext.Object, identity, newCookieToken)).Returns(formToken);
mockValidator.Setup(o => o.IsCookieTokenValid(null)).Returns(false);
mockValidator.Setup(o => o.IsCookieTokenValid(newCookieToken)).Returns(true);
mockValidator.Setup(o => o.GenerateCookieToken()).Returns(newCookieToken);
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: mockSerializer.Object,
tokenStore: null,
validator: mockValidator.Object);
// Act
string serializedNewCookieToken, serializedFormToken;
worker.GetTokens(mockHttpContext.Object, "serialized-old-cookie-token", out serializedNewCookieToken, out serializedFormToken);
// Assert
Assert.Equal("serialized-new-cookie-token", serializedNewCookieToken);
Assert.Equal("serialized-form-token", serializedFormToken);
}
[Fact]
public void GetTokens_ExistingValidCookieToken()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken cookieToken = new AntiForgeryToken() { IsSessionToken = true };
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>(MockBehavior.Strict);
mockSerializer.Setup(o => o.Deserialize("serialized-old-cookie-token")).Returns(cookieToken);
mockSerializer.Setup(o => o.Serialize(formToken)).Returns("serialized-form-token");
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>(MockBehavior.Strict);
mockValidator.Setup(o => o.GenerateFormToken(mockHttpContext.Object, identity, cookieToken)).Returns(formToken);
mockValidator.Setup(o => o.IsCookieTokenValid(cookieToken)).Returns(true);
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: mockSerializer.Object,
tokenStore: null,
validator: mockValidator.Object);
// Act
string serializedNewCookieToken, serializedFormToken;
worker.GetTokens(mockHttpContext.Object, "serialized-old-cookie-token", out serializedNewCookieToken, out serializedFormToken);
// Assert
Assert.Null(serializedNewCookieToken);
Assert.Equal("serialized-form-token", serializedFormToken);
}
[Fact]
public void Validate_FromStrings_Failure()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken cookieToken = new AntiForgeryToken();
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Deserialize("cookie-token")).Returns(cookieToken);
mockSerializer.Setup(o => o.Deserialize("form-token")).Returns(formToken);
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>();
mockValidator.Setup(o => o.ValidateTokens(mockHttpContext.Object, identity, cookieToken, formToken)).Throws(new HttpAntiForgeryException("my-message"));
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: mockSerializer.Object,
tokenStore: null,
validator: mockValidator.Object);
// Act & assert
var ex = Assert.Throws<HttpAntiForgeryException>(() => worker.Validate(mockHttpContext.Object, "cookie-token", "form-token"));
Assert.Equal("my-message", ex.Message);
}
[Fact]
public void Validate_FromStrings_Success()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken cookieToken = new AntiForgeryToken();
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableAntiForgeryTokenSerializer> mockSerializer = new Mock<MockableAntiForgeryTokenSerializer>();
mockSerializer.Setup(o => o.Deserialize("cookie-token")).Returns(cookieToken);
mockSerializer.Setup(o => o.Deserialize("form-token")).Returns(formToken);
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>();
mockValidator.Setup(o => o.ValidateTokens(mockHttpContext.Object, identity, cookieToken, formToken)).Verifiable();
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: mockSerializer.Object,
tokenStore: null,
validator: mockValidator.Object);
// Act
worker.Validate(mockHttpContext.Object, "cookie-token", "form-token");
// Assert
mockValidator.Verify();
}
[Fact]
public void Validate_FromStore_Failure()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken cookieToken = new AntiForgeryToken();
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableTokenStore> mockTokenStore = new Mock<MockableTokenStore>();
mockTokenStore.Setup(o => o.GetCookieToken(mockHttpContext.Object)).Returns(cookieToken);
mockTokenStore.Setup(o => o.GetFormToken(mockHttpContext.Object)).Returns(formToken);
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>();
mockValidator.Setup(o => o.ValidateTokens(mockHttpContext.Object, identity, cookieToken, formToken)).Throws(new HttpAntiForgeryException("my-message"));
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: null,
tokenStore: mockTokenStore.Object,
validator: mockValidator.Object);
// Act & assert
var ex = Assert.Throws<HttpAntiForgeryException>(() => worker.Validate(mockHttpContext.Object));
Assert.Equal("my-message", ex.Message);
}
[Fact]
public void Validate_FromStore_Success()
{
// Arrange
GenericIdentity identity = new GenericIdentity("some-user");
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(o => o.User).Returns(new GenericPrincipal(identity, new string[0]));
AntiForgeryToken cookieToken = new AntiForgeryToken();
AntiForgeryToken formToken = new AntiForgeryToken();
Mock<MockableTokenStore> mockTokenStore = new Mock<MockableTokenStore>();
mockTokenStore.Setup(o => o.GetCookieToken(mockHttpContext.Object)).Returns(cookieToken);
mockTokenStore.Setup(o => o.GetFormToken(mockHttpContext.Object)).Returns(formToken);
Mock<MockableTokenValidator> mockValidator = new Mock<MockableTokenValidator>();
mockValidator.Setup(o => o.ValidateTokens(mockHttpContext.Object, identity, cookieToken, formToken)).Verifiable();
AntiForgeryWorker worker = new AntiForgeryWorker(
config: new MockAntiForgeryConfig(),
serializer: null,
tokenStore: mockTokenStore.Object,
validator: mockValidator.Object);
// Act
worker.Validate(mockHttpContext.Object);
// Assert
mockValidator.Verify();
}
}
}

View File

@ -0,0 +1,129 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class BinaryBlobTest
{
[Fact]
public void Ctor_BitLength()
{
// Act
BinaryBlob blob = new BinaryBlob(bitLength: 64);
byte[] data = blob.GetData();
// Assert
Assert.Equal(64, blob.BitLength);
Assert.Equal(64 / 8, data.Length);
Assert.NotEqual(new byte[64 / 8], data); // should not be a zero-filled array
}
[Theory]
[InlineData(24)]
[InlineData(33)]
public void Ctor_BitLength_Bad(int bitLength)
{
// Act & assert
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new BinaryBlob(bitLength));
Assert.Equal("bitLength", ex.ParamName);
}
[Fact]
public void Ctor_BitLength_ProducesDifferentValues()
{
// Act
BinaryBlob blobA = new BinaryBlob(bitLength: 64);
BinaryBlob blobB = new BinaryBlob(bitLength: 64);
// Assert
Assert.NotEqual(blobA.GetData(), blobB.GetData());
}
[Fact]
public void Ctor_Data()
{
// Arrange
byte[] expectedData = new byte[] { 0x01, 0x02, 0x03, 0x04 };
// Act
BinaryBlob blob = new BinaryBlob(32, expectedData);
// Assert
Assert.Equal(32, blob.BitLength);
Assert.Equal(expectedData, blob.GetData());
}
[Theory]
[InlineData((object[])null)]
[InlineData(new byte[] { 0x01, 0x02, 0x03 })]
public void Ctor_Data_Bad(byte[] data)
{
// Act & assert
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new BinaryBlob(32, data));
Assert.Equal("data", ex.ParamName);
}
[Fact]
public void Equals_DifferentData_ReturnsFalse()
{
// Arrange
object blobA = new BinaryBlob(32, new byte[] { 0x01, 0x02, 0x03, 0x04 });
object blobB = new BinaryBlob(32, new byte[] { 0x04, 0x03, 0x02, 0x01 });
// Act & assert
Assert.NotEqual(blobA, blobB);
}
[Fact]
public void Equals_NotABlob_ReturnsFalse()
{
// Arrange
object blobA = new BinaryBlob(32);
object blobB = "hello";
// Act & assert
Assert.NotEqual(blobA, blobB);
}
[Fact]
public void Equals_Null_ReturnsFalse()
{
// Arrange
object blobA = new BinaryBlob(32);
object blobB = null;
// Act & assert
Assert.NotEqual(blobA, blobB);
}
[Fact]
public void Equals_SameData_ReturnsTrue()
{
// Arrange
object blobA = new BinaryBlob(32, new byte[] { 0x01, 0x02, 0x03, 0x04 });
object blobB = new BinaryBlob(32, new byte[] { 0x01, 0x02, 0x03, 0x04 });
// Act & assert
Assert.Equal(blobA, blobB);
}
[Fact]
public void GetHashCodeTest()
{
// Arrange
byte[] blobData = new byte[] { 0x01, 0x02, 0x03, 0x04 };
int expectedHashCode = BitConverter.ToInt32(blobData, 0);
BinaryBlob blob = new BinaryBlob(32, blobData);
// Act
int actualHashCode = blob.GetHashCode();
// Assert
Assert.Equal(expectedHashCode, actualHashCode);
}
}
}

View File

@ -0,0 +1,239 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Reflection;
using System.Security.Principal;
using System.Web.Helpers.Claims;
using System.Web.Helpers.Claims.Test;
using System.Web.Helpers.Test;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class ClaimUidExtractorTest
{
[Fact]
public void ExtractClaimUid_NullIdentity()
{
// Arrange
ClaimUidExtractor extractor = new ClaimUidExtractor(
config: null,
claimsIdentityConverter: null);
// Act
BinaryBlob retVal = extractor.ExtractClaimUid(null);
// Assert
Assert.Null(retVal);
}
[Fact]
public void ExtractClaimUid_Unauthenticated()
{
// Arrange
ClaimUidExtractor extractor = new ClaimUidExtractor(
config: null,
claimsIdentityConverter: null);
Mock<IIdentity> mockIdentity = new Mock<IIdentity>();
mockIdentity.Setup(o => o.IsAuthenticated).Returns(false);
// Act
BinaryBlob retVal = extractor.ExtractClaimUid(mockIdentity.Object);
// Assert
Assert.Null(retVal);
}
[Fact]
public void ExtractClaimUid_ClaimsIdentityHeuristicsSuppressed()
{
// Arrange
GenericIdentity identity = new GenericIdentity("the-user");
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
SuppressIdentityHeuristicChecks = true
};
ClaimUidExtractor extractor = new ClaimUidExtractor(
config: config,
claimsIdentityConverter: null);
// Act
BinaryBlob retVal = extractor.ExtractClaimUid(identity);
// Assert
Assert.Null(retVal);
}
[Fact]
public void ExtractClaimUid_NotAClaimsIdentity()
{
// Arrange
Mock<IIdentity> mockIdentity = new Mock<IIdentity>();
mockIdentity.Setup(o => o.IsAuthenticated).Returns(true);
MockAntiForgeryConfig config = new MockAntiForgeryConfig();
ClaimsIdentityConverter converter = new ClaimsIdentityConverter(new Func<IIdentity, ClaimsIdentity>[0]);
ClaimUidExtractor extractor = new ClaimUidExtractor(
config: config,
claimsIdentityConverter: converter);
// Act
BinaryBlob retVal = extractor.ExtractClaimUid(mockIdentity.Object);
// Assert
Assert.Null(retVal);
}
[Fact]
public void ExtractClaimUid_ClaimsIdentity()
{
// Arrange
Mock<IIdentity> mockIdentity = new Mock<IIdentity>();
mockIdentity.Setup(o => o.IsAuthenticated).Returns(true);
MockAntiForgeryConfig config = new MockAntiForgeryConfig()
{
UniqueClaimTypeIdentifier = "unique-identifier"
};
ClaimsIdentityConverter converter = new ClaimsIdentityConverter(new Func<IIdentity, ClaimsIdentity>[] {
identity =>
{
Assert.Equal(mockIdentity.Object, identity);
MockClaimsIdentity claimsIdentity = new MockClaimsIdentity();
claimsIdentity.AddClaim("unique-identifier", "some-value");
return claimsIdentity;
}
});
ClaimUidExtractor extractor = new ClaimUidExtractor(
config: config,
claimsIdentityConverter: converter);
// Act
BinaryBlob retVal = extractor.ExtractClaimUid(mockIdentity.Object);
// Assert
Assert.NotNull(retVal);
Assert.Equal("CA9CCFF86F903FBB7505BAAA9F222E49EC2A1E8FAD630AE73DE180BD679751ED", HexUtil.HexEncode(retVal.GetData()));
}
[Theory]
[DefaultUniqueClaimTypes_NotPresent_Data]
public void DefaultUniqueClaimTypes_NotPresent_Throws(object identity)
{
// Arrange
ClaimsIdentity claimsIdentity = (ClaimsIdentity)identity;
// Act & assert
var ex = Assert.Throws<InvalidOperationException>(() => ClaimUidExtractor.GetUniqueIdentifierParameters(claimsIdentity, null));
Assert.Equal(@"A claim of type 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' or 'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' was not present on the provided ClaimsIdentity. To enable anti-forgery token support with claims-based authentication, please verify that the configured claims provider is providing both of these claims on the ClaimsIdentity instances it generates. If the configured claims provider instead uses a different claim type as a unique identifier, it can be configured by setting the static property AntiForgeryConfig.UniqueClaimTypeIdentifier.", ex.Message);
}
[Fact]
public void DefaultUniqueClaimTypes_Present()
{
// Arrange
MockClaimsIdentity identity = new MockClaimsIdentity();
identity.AddClaim("fooClaim", "fooClaimValue");
identity.AddClaim(ClaimUidExtractor.NameIdentifierClaimType, "nameIdentifierValue");
identity.AddClaim(ClaimUidExtractor.IdentityProviderClaimType, "identityProviderValue");
// Act
var retVal = ClaimUidExtractor.GetUniqueIdentifierParameters(identity, null);
// Assert
Assert.Equal(new string[] {
ClaimUidExtractor.NameIdentifierClaimType,
"nameIdentifierValue",
ClaimUidExtractor.IdentityProviderClaimType,
"identityProviderValue"
}, retVal);
}
[Fact]
public void ExplicitUniqueClaimType_Present()
{
// Arrange
MockClaimsIdentity identity = new MockClaimsIdentity();
identity.AddClaim("fooClaim", "fooClaimValue");
identity.AddClaim(ClaimUidExtractor.NameIdentifierClaimType, "nameIdentifierValue");
identity.AddClaim(ClaimUidExtractor.IdentityProviderClaimType, "identityProviderValue");
// Act
var retVal = ClaimUidExtractor.GetUniqueIdentifierParameters(identity, "fooClaim");
// Assert
Assert.Equal(new string[] {
"fooClaim",
"fooClaimValue"
}, retVal);
}
[Theory]
[ExplicitUniqueClaimType_NotPresent_Data]
public void ExplicitUniqueClaimType_NotPresent_Throws(object identity)
{
// Arrange
ClaimsIdentity claimsIdentity = (ClaimsIdentity)identity;
// Act & assert
var ex = Assert.Throws<InvalidOperationException>(() => ClaimUidExtractor.GetUniqueIdentifierParameters(claimsIdentity, "fooClaim"));
Assert.Equal(@"A claim of type 'fooClaim' was not present on the provided ClaimsIdentity.", ex.Message);
}
private sealed class DefaultUniqueClaimTypes_NotPresent_DataAttribute : DataAttribute
{
public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
{
MockClaimsIdentity identity1 = new MockClaimsIdentity();
identity1.AddClaim(ClaimUidExtractor.IdentityProviderClaimType, "identityProviderValue");
yield return new object[] { identity1 };
MockClaimsIdentity identity2 = new MockClaimsIdentity();
identity2.AddClaim(ClaimUidExtractor.NameIdentifierClaimType, String.Empty);
identity2.AddClaim(ClaimUidExtractor.IdentityProviderClaimType, "identityProviderValue");
yield return new object[] { identity2 };
MockClaimsIdentity identity3 = new MockClaimsIdentity();
identity3.AddClaim(ClaimUidExtractor.NameIdentifierClaimType, "nameIdentifierValue");
yield return new object[] { identity3 };
MockClaimsIdentity identity4 = new MockClaimsIdentity();
identity4.AddClaim(ClaimUidExtractor.NameIdentifierClaimType, "nameIdentifierValue");
identity4.AddClaim(ClaimUidExtractor.IdentityProviderClaimType, String.Empty);
yield return new object[] { identity4 };
MockClaimsIdentity identity5 = new MockClaimsIdentity();
identity5.AddClaim(ClaimUidExtractor.NameIdentifierClaimType.ToUpper(), "nameIdentifierValue");
identity5.AddClaim(ClaimUidExtractor.IdentityProviderClaimType.ToUpper(), "identityProviderValue");
yield return new object[] { identity5 };
}
}
private sealed class ExplicitUniqueClaimType_NotPresent_DataAttribute : DataAttribute
{
public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
{
MockClaimsIdentity identity1 = new MockClaimsIdentity();
yield return new object[] { identity1 };
MockClaimsIdentity identity2 = new MockClaimsIdentity();
identity2.AddClaim("fooClaim", String.Empty);
yield return new object[] { identity2 };
MockClaimsIdentity identity3 = new MockClaimsIdentity();
identity3.AddClaim("FOOCLAIM", "fooClaimValue");
yield return new object[] { identity3 };
MockClaimsIdentity identity4 = new MockClaimsIdentity();
identity4.AddClaim(ClaimUidExtractor.NameIdentifierClaimType, "nameIdentifierValue");
identity4.AddClaim(ClaimUidExtractor.IdentityProviderClaimType, "identityProviderValue");
yield return new object[] { identity4 };
}
}
}
}

View File

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace System.Web.Helpers.AntiXsrf.Test
{
internal static class HexUtil
{
public static string HexEncode(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length * 2);
foreach (byte b in data)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}", b);
}
return sb.ToString();
}
public static byte[] HexDecode(string input)
{
List<byte> bytes = new List<byte>(input.Length / 2);
for (int i = 0; i < input.Length; i += 2)
{
bytes.Add(Byte.Parse(input.Substring(i, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture));
}
return bytes.ToArray();
}
}
}

View File

@ -0,0 +1,122 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Security;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class MachineKeyCryptoSystemTest
{
private static readonly MachineKeyCryptoSystem _dummyCryptoSystem = new MachineKeyCryptoSystem(HexEncoder, HexDecoder);
[Fact]
public void Base64ToHex()
{
// Arrange
string base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_0";
string hex = "00108310518720928B30D38F41149351559761969B71D79F8218A39259A7A29AABB2DBAFC31CB3D35DB7E39EBBF3DFBF";
// Act
string retVal = MachineKeyCryptoSystem.Base64ToHex(base64);
// Assert
Assert.Equal(hex, retVal);
}
[Fact]
public void Base64ToHex_HexToBase64_RoundTrips()
{
for (int i = 0; i <= Byte.MaxValue; i++)
{
// Arrange
string hex = String.Format("{0:X2}", i);
// Act
string retVal = MachineKeyCryptoSystem.Base64ToHex(MachineKeyCryptoSystem.HexToBase64(hex));
// Assert
Assert.Equal(hex, retVal);
}
}
[Fact]
public void HexToBase64()
{
// Arrange
string base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_0";
string hex = "00108310518720928B30D38F41149351559761969B71D79F8218A39259A7A29AABB2DBAFC31CB3D35DB7E39EBBF3DFBF";
// Act
string retVal = MachineKeyCryptoSystem.HexToBase64(hex);
// Assert
Assert.Equal(base64, retVal);
}
[Fact]
public void Protect()
{
// Arrange
byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };
// Act
string retVal = _dummyCryptoSystem.Protect(data);
// Assert
Assert.Equal("hYfyZgECAwQF0", retVal);
}
[Theory]
[InlineData("hYfyZwECAwQF0")] // bad MagicHeader
[InlineData("hYfy0")] // too short to contain MagicHeader
public void Unprotect_Failure(string protectedData)
{
// Act
byte[] retVal = _dummyCryptoSystem.Unprotect(protectedData);
// Assert
Assert.Null(retVal);
}
[Fact]
public void Unprotect_Success()
{
// Arrange
byte[] expected = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };
// Act
byte[] retVal = _dummyCryptoSystem.Unprotect("hYfyZgECAwQF0");
// Assert
Assert.Equal(expected, retVal);
}
[Fact]
public void Protect_Unprotect_RoundTrips()
{
// Arrange
byte[] data = new byte[1024];
new Random().NextBytes(data);
// Act
byte[] roundTripped = _dummyCryptoSystem.Unprotect(_dummyCryptoSystem.Protect(data));
// Assert
Assert.Equal(data, roundTripped);
}
private static string HexEncoder(byte[] data, MachineKeyProtection protection)
{
Assert.Equal(MachineKeyProtection.All, protection);
return HexUtil.HexEncode(data);
}
private static byte[] HexDecoder(string input, MachineKeyProtection protection)
{
Assert.Equal(MachineKeyProtection.All, protection);
return HexUtil.HexDecode(input);
}
}
}

Some files were not shown because too many files have changed in this diff Show More