Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

1165 lines
43 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web.WebPages.TestUtils;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.Test
{
public class WebImageTest
{
private static readonly byte[] _JpgImageBytes = TestFile.Create("LambdaFinal.jpg").ReadAllBytes();
private static readonly byte[] _BmpImageBytes = TestFile.Create("logo.bmp").ReadAllBytes();
private static readonly byte[] _PngImageBytes = TestFile.Create("NETLogo.png").ReadAllBytes();
private static readonly byte[] _HiResImageBytes = TestFile.Create("HiRes.jpg").ReadAllBytes();
[Fact]
public void ConstructorThrowsWhenFilePathIsNull()
{
Assert.ThrowsArgument(() =>
new WebImage(GetContext(), s => new byte[] { }, filePath: null), "filePath", "Value cannot be null or an empty string.");
}
[Fact]
public void ConstructorThrowsWhenFilePathIsEmpty()
{
Assert.ThrowsArgument(() =>
new WebImage(GetContext(), s => new byte[] { }, filePath: String.Empty), "filePath", "Value cannot be null or an empty string.");
}
[Fact]
public void ConstructorThrowsWhenFilePathIsInvalid()
{
Assert.Throws<DirectoryNotFoundException>(() =>
new WebImage(GetContext(), s => { throw new DirectoryNotFoundException(); }, @"x:\this\does\not\exist.jpg"));
}
[Fact]
public void ConstructorThrowsWhenFileContentIsInvalid()
{
byte[] imageContent = new byte[] { 32, 111, 209, 138, 76, 32 };
Assert.ThrowsArgument(() => new WebImage(imageContent), "content",
"An image could not be constructed from the content provided.");
}
[Fact]
public void FilePathReturnsCorrectPath()
{
// Arrange
string imageName = @"x:\My-test-image.png";
// Act
WebImage image = new WebImage(GetContext(), s => _PngImageBytes, imageName);
// Assert
Assert.Equal(imageName, image.FileName);
}
[Fact]
public void FilePathCanBeSet()
{
// Arrange
string originalPath = @"x:\somePath.png";
string newPath = @"x:\someOtherPath.jpg";
// Act
WebImage image = new WebImage(GetContext(), s => _PngImageBytes, originalPath);
image.FileName = newPath;
// Assert
Assert.Equal(newPath, image.FileName);
}
[Fact]
public void SimpleGetBytesClonesArray()
{
WebImage image = new WebImage(_PngImageBytes);
byte[] returnedContent = image.GetBytes();
Assert.False(ReferenceEquals(_PngImageBytes, returnedContent), "GetBytes should clone array.");
Assert.Equal(_PngImageBytes, returnedContent);
}
[Fact]
public void WebImagePreservesOriginalFormatFromFile()
{
WebImage image = new WebImage(_PngImageBytes);
byte[] returnedContent = image.GetBytes();
// If format was changed; content would be different
Assert.Equal(_PngImageBytes, returnedContent);
}
[Fact]
public void WebImagePreservesOriginalFormatFromStream()
{
WebImage image = null;
byte[] originalContent = _PngImageBytes;
using (MemoryStream stream = new MemoryStream(originalContent))
{
image = new WebImage(stream);
} // dispose stream; WebImage should have no dependency on it
byte[] returnedContent = image.GetBytes();
// If format was changed; content would be different
Assert.Equal(originalContent, returnedContent);
}
[Fact]
public void WebImageCorrectlyReadsFromNoSeekStream()
{
WebImage image = null;
byte[] originalContent = _PngImageBytes;
using (MemoryStream stream = new MemoryStream(originalContent))
{
TestStream ts = new TestStream(stream);
image = new WebImage(ts);
} // dispose stream; WebImage should have no dependency on it
byte[] returnedContent = image.GetBytes();
// If chunks are not assembled correctly; content would be different and image would be corrupted.
Assert.Equal(originalContent, returnedContent);
Assert.Equal("png", image.ImageFormat);
}
[Fact]
public void GetBytesWithNullReturnsClonesArray()
{
byte[] originalContent = _BmpImageBytes;
WebImage image = new WebImage(originalContent);
byte[] returnedContent = image.GetBytes();
Assert.False(ReferenceEquals(originalContent, returnedContent), "GetBytes with string null should clone array.");
Assert.Equal(originalContent, returnedContent);
}
[Fact]
public void GetBytesWithSameFormatReturnsSameFormat()
{
byte[] originalContent = _JpgImageBytes;
WebImage image = new WebImage(originalContent);
byte[] returnedContent = image.GetBytes("jpeg");
Assert.False(ReferenceEquals(originalContent, returnedContent), "GetBytes with string null should clone array.");
Assert.Equal(originalContent, returnedContent);
}
[Fact]
public void GetBytesWithDifferentFormatReturnsExpectedFormat()
{
byte[] originalContent = _BmpImageBytes;
WebImage image = new WebImage(originalContent);
// Request different format
byte[] returnedContent = image.GetBytes("jpg");
Assert.False(ReferenceEquals(originalContent, returnedContent), "GetBytes with string format should clone array.");
using (MemoryStream stream = new MemoryStream(returnedContent))
{
using (Image tempImage = Image.FromStream(stream))
{
Assert.Equal(ImageFormat.Jpeg, tempImage.RawFormat);
}
}
}
[Fact]
public void GetBytesWithSameFormatReturnsSameFormatWhenCreatedFromFile()
{
byte[] originalContent = _BmpImageBytes;
// Format is not set during construction.
WebImage image = new WebImage(_BmpImageBytes);
byte[] returnedContent = image.GetBytes("bmp");
Assert.False(ReferenceEquals(originalContent, returnedContent), "GetBytes with string format should clone array.");
Assert.Equal(originalContent, returnedContent);
}
[Fact]
public void GetBytesWithNoFormatReturnsInitialFormatEvenAfterTransformations()
{
byte[] originalContent = _BmpImageBytes;
// Format is not set during construction.
WebImage image = new WebImage(_BmpImageBytes);
image.Crop(top: 10, bottom: 10);
byte[] returnedContent = image.GetBytes();
Assert.NotEqual(originalContent, returnedContent);
using (MemoryStream stream = new MemoryStream(returnedContent))
{
using (Image tempImage = Image.FromStream(stream))
{
Assert.Equal(ImageFormat.Bmp, tempImage.RawFormat);
}
}
}
[Fact]
public void GetBytesThrowsOnIncorrectFormat()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgument(
() => image.GetBytes("bmpx"),
"format",
"\"bmpx\" is invalid image format. Valid values are image format names like: \"JPEG\", \"BMP\", \"GIF\", \"PNG\", etc.");
}
[Fact]
public void GetBytesWithDifferentFormatReturnsExpectedFormatWhenCreatedFromFile()
{
// Format is not set during construction.
WebImage image = new WebImage(_PngImageBytes);
// Request different format
byte[] returnedContent = image.GetBytes("jpg");
WebImage newImage = new WebImage(returnedContent);
Assert.Equal("jpeg", newImage.ImageFormat);
}
[Fact]
public void GetImageFromRequestReturnsNullForIncorrectMimeType()
{
// Arrange
Mock<HttpPostedFileBase> postedFile = new Mock<HttpPostedFileBase>();
postedFile.Setup(c => c.FileName).Returns("index.cshtml");
postedFile.Setup(c => c.ContentType).Returns("image/jpg");
Mock<HttpFileCollectionBase> files = new Mock<HttpFileCollectionBase>();
files.Setup(c => c[0]).Returns(postedFile.Object);
Mock<HttpRequestBase> request = new Mock<HttpRequestBase>();
request.Setup(r => r.Files).Returns(files.Object);
// Act and Assert
Assert.Null(WebImage.GetImageFromRequest(request.Object));
}
[Fact]
public void GetImageFromRequestDeterminesMimeTypeFromExtension()
{
// Arrange
Mock<HttpPostedFileBase> postedFile = new Mock<HttpPostedFileBase>();
postedFile.Setup(c => c.FileName).Returns("index.jpeg");
postedFile.Setup(c => c.ContentType).Returns("application/octet-stream");
postedFile.Setup(c => c.ContentLength).Returns(1);
postedFile.Setup(c => c.InputStream).Returns(new MemoryStream(_JpgImageBytes));
Mock<HttpFileCollectionBase> files = new Mock<HttpFileCollectionBase>();
files.Setup(c => c.Count).Returns(1);
files.Setup(c => c[0]).Returns(postedFile.Object);
Mock<HttpRequestBase> request = new Mock<HttpRequestBase>();
request.Setup(r => r.Files).Returns(files.Object);
// Act
WebImage image = WebImage.GetImageFromRequest(request.Object);
// Assert
Assert.NotNull(image);
Assert.Equal("jpeg", image.ImageFormat);
}
[Fact]
public void GetImageFromRequestIsCaseInsensitive()
{
// Arrange
Mock<HttpPostedFileBase> postedFile = new Mock<HttpPostedFileBase>();
postedFile.SetupGet(c => c.FileName).Returns("index.JPg");
postedFile.SetupGet(c => c.ContentType).Returns("application/octet-stream");
postedFile.SetupGet(c => c.ContentLength).Returns(1);
postedFile.SetupGet(c => c.InputStream).Returns(new MemoryStream(_JpgImageBytes));
Mock<HttpFileCollectionBase> files = new Mock<HttpFileCollectionBase>();
files.Setup(c => c.Count).Returns(1);
files.Setup(c => c[0]).Returns(postedFile.Object);
Mock<HttpRequestBase> request = new Mock<HttpRequestBase>();
request.Setup(r => r.Files).Returns(files.Object);
// Act
WebImage image = WebImage.GetImageFromRequest(request.Object);
// Assert
Assert.NotNull(image);
Assert.Equal("jpeg", image.ImageFormat);
}
[Fact]
public void ImagePropertiesAreCorrectForBmpImage()
{
WebImage image = new WebImage(_BmpImageBytes);
Assert.Equal("bmp", image.ImageFormat);
Assert.Equal(108, image.Width);
Assert.Equal(44, image.Height);
}
[Fact]
public void ImagePropertiesAreCorrectForPngImage()
{
WebImage image = new WebImage(_PngImageBytes);
Assert.Equal("png", image.ImageFormat);
Assert.Equal(160, image.Width);
Assert.Equal(152, image.Height);
}
[Fact]
public void ImagePropertiesAreCorrectForJpgImage()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Equal("jpeg", image.ImageFormat);
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void ResizePreservesRatio()
{
WebImage image = new WebImage(_JpgImageBytes);
image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true);
Assert.Equal(130, image.Width);
Assert.Equal(100, image.Height);
}
[Fact]
public void ResizePreservesResolution()
{
MemoryStream output = null;
Action<string, byte[]> saveAction = (_, content) => { output = new MemoryStream(content); };
WebImage image = new WebImage(_HiResImageBytes);
image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true);
image.Save(GetContext(), saveAction, @"x:\ResizePreservesResolution.jpg", "jpeg", forceWellKnownExtension: true);
using (Image original = Image.FromStream(new MemoryStream(_HiResImageBytes)))
{
using (Image modified = Image.FromStream(output))
{
Assert.Equal(original.HorizontalResolution, modified.HorizontalResolution);
Assert.Equal(original.VerticalResolution, modified.VerticalResolution);
}
}
}
[Fact]
public void ResizePreservesFormat()
{
// Arrange
WebImage image = new WebImage(_PngImageBytes);
MemoryStream output = null;
Action<string, byte[]> saveAction = (_, content) => { output = new MemoryStream(content); };
// Act
image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true);
// Assert
Assert.Equal(image.ImageFormat, "png");
image.Save(GetContext(), saveAction, @"x:\1.png", null, false);
using (Image modified = Image.FromStream(output))
{
Assert.Equal(ImageFormat.Png, modified.RawFormat);
}
}
[Fact]
public void SaveUpdatesFileNameOfWebImageWhenForcingWellKnownExtension()
{
// Arrange
var context = GetContext();
// Act
WebImage image = new WebImage(context, _ => _JpgImageBytes, @"c:\images\foo.jpg");
image.Save(context, (_, __) => { }, @"x:\1.exe", "jpg", forceWellKnownExtension: true);
// Assert
Assert.Equal(@"x:\1.exe.jpeg", image.FileName);
}
[Fact]
public void SaveUpdatesFileNameOfWebImageWhenFormatChanges()
{
// Arrange
string imagePath = @"x:\images\foo.jpg";
var context = GetContext();
// Act
WebImage image = new WebImage(context, _ => _JpgImageBytes, imagePath);
image.Save(context, (_, __) => { }, imagePath, "png", forceWellKnownExtension: true);
// Assert
Assert.Equal(@"x:\images\foo.jpg.png", image.FileName);
}
[Fact]
public void SaveKeepsNameIfFormatIsUnchanged()
{
// Arrange
string imagePath = @"x:\images\foo.jpg";
var context = GetContext();
// Act
WebImage image = new WebImage(context, _ => _JpgImageBytes, imagePath);
image.Save(context, (_, __) => { }, imagePath, "jpg", forceWellKnownExtension: true);
// Assert
Assert.Equal(@"x:\images\foo.jpg", image.FileName);
}
[Fact]
public void ResizeThrowsOnIncorrectWidthOrHeight()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentGreaterThan(
() => image.Resize(-1, 100, preserveAspectRatio: true, preventEnlarge: true),
"width",
"0");
Assert.ThrowsArgumentGreaterThan(
() => image.Resize(100, -1, preserveAspectRatio: true, preventEnlarge: true),
"height",
"0");
}
[Fact]
public void ResizeAndRotateDoesOperationsInRightOrder()
{
WebImage image = new WebImage(_JpgImageBytes);
image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true).RotateLeft();
Assert.Equal(100, image.Width);
Assert.Equal(130, image.Height);
}
[Fact]
public void ClonePreservesAllInformation()
{
WebImage image = new WebImage(_JpgImageBytes);
image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true).RotateLeft();
// this should preserve list of transformations
WebImage cloned = image.Clone();
Assert.Equal(100, cloned.Width);
Assert.Equal(130, cloned.Height);
}
[Fact]
public void ResizePreventsEnlarge()
{
WebImage image = new WebImage(_JpgImageBytes);
int height = image.Height;
int width = image.Width;
image.Resize(width * 2, height, preserveAspectRatio: true, preventEnlarge: true);
Assert.Equal(width, image.Width);
Assert.Equal(height, image.Height);
}
[Fact]
public void CropCreatesCroppedImage()
{
WebImage image = new WebImage(_JpgImageBytes);
image.Crop(20, 20, 20, 20);
Assert.Equal(594, image.Width);
Assert.Equal(449, image.Height);
}
[Fact]
public void CropThrowsOnIncorrectArguments()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.Crop(top: -1),
"top",
"0");
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.Crop(left: -1),
"left",
"0");
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.Crop(bottom: -1),
"bottom",
"0");
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.Crop(right: -1),
"right",
"0");
}
[Fact]
public void RotateLeftReturnsRotatedImage()
{
WebImage image = new WebImage(_PngImageBytes);
image.RotateLeft();
Assert.Equal(152, image.Width);
Assert.Equal(160, image.Height);
}
[Fact]
public void RotateRightReturnsRotatedImage()
{
WebImage image = new WebImage(_PngImageBytes);
image.RotateRight();
Assert.Equal(152, image.Width);
Assert.Equal(160, image.Height);
}
[Fact]
public void FlipVerticalReturnsFlippedImage()
{
WebImage image = new WebImage(_PngImageBytes);
image.FlipVertical();
Assert.Equal(160, image.Width);
Assert.Equal(152, image.Height);
}
[Fact]
public void FlipHorizontalReturnsFlippedImage()
{
WebImage image = new WebImage(_PngImageBytes);
image.FlipHorizontal();
Assert.Equal(160, image.Width);
Assert.Equal(152, image.Height);
}
[Fact]
public void MultipleCombinedOperationsExecuteInRightOrder()
{
WebImage image = new WebImage(_JpgImageBytes);
image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true).RotateLeft();
image.Crop(top: 10, right: 10).AddTextWatermark("plan9");
Assert.Equal(90, image.Width);
Assert.Equal(120, image.Height);
}
[Fact]
public void AddTextWatermarkPreservesImageDimension()
{
WebImage image = new WebImage(_JpgImageBytes);
image.AddTextWatermark("Plan9", fontSize: 16, horizontalAlign: "Left", verticalAlign: "Bottom", opacity: 50);
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void AddTextWatermarkParsesHexColorCorrectly()
{
WebImage image = new WebImage(_JpgImageBytes);
image.AddTextWatermark("Plan9", fontSize: 16, fontColor: "#FF0000", horizontalAlign: "Center", verticalAlign: "Middle");
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void AddTextWatermarkParsesShortHexColorCorrectly()
{
WebImage image = new WebImage(_JpgImageBytes);
image.AddTextWatermark("Plan9", fontSize: 16, fontColor: "#F00", horizontalAlign: "Center", verticalAlign: "Middle");
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void AddTextWatermarkDoesNotChangeImageIfPaddingIsTooBig()
{
WebImage image = new WebImage(_JpgImageBytes);
image.AddTextWatermark("Plan9", padding: 1000);
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void AddTextWatermarkThrowsOnNegativeOpacity()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentOutOfRange(() => image.AddTextWatermark("Plan9", opacity: -1), "opacity", "Value must be between 0 and 100.");
}
[Fact]
public void AddTextWatermarkThrowsOnTooBigOpacity()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentOutOfRange(() => image.AddTextWatermark("Plan9", opacity: 155), "opacity", "Value must be between 0 and 100.");
}
[Fact]
public void AddTextWatermarkThrowsOnEmptyText()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentNullOrEmptyString(
() => image.AddTextWatermark(""),
"text");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectColorName()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", fontColor: "super"),
"The \"fontColor\" value is invalid. Valid values are names like \"White\", \"Black\", or \"DarkBlue\", or hexadecimal values in the form \"#RRGGBB\" or \"#RGB\".");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectHexColorValue()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", fontColor: "#XXX"),
"The \"fontColor\" value is invalid. Valid values are names like \"White\", \"Black\", or \"DarkBlue\", or hexadecimal values in the form \"#RRGGBB\" or \"#RGB\".");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectHexColorLength()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", fontColor: "#F000"),
"The \"fontColor\" value is invalid. Valid values are names like \"White\", \"Black\", or \"DarkBlue\", or hexadecimal values in the form \"#RRGGBB\" or \"#RGB\".");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectHorizontalAlignment()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", horizontalAlign: "Justify"),
"The \"horizontalAlign\" value is invalid. Valid values are: \"Right\", \"Left\", and \"Center\".");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectVerticalAlignment()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", verticalAlign: "NotSet"),
"The \"verticalAlign\" value is invalid. Valid values are: \"Top\", \"Bottom\", and \"Middle\".");
}
[Fact]
public void AddTextWatermarkThrowsOnNegativePadding()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.AddTextWatermark("p9", padding: -10),
"padding",
"0");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectFontSize()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentGreaterThan(
() => image.AddTextWatermark("p9", fontSize: -10),
"fontSize",
"0");
Assert.ThrowsArgumentGreaterThan(
() => image.AddTextWatermark("p9", fontSize: 0),
"fontSize",
"0");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectFontStyle()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", fontStyle: "something"),
"The \"fontStyle\" value is invalid. Valid values are: \"Regular\", \"Bold\", \"Italic\", \"Underline\", and \"Strikeout\".");
}
[Fact]
public void AddTextWatermarkThrowsOnIncorrectFontFamily()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddTextWatermark("p9", fontFamily: "something"),
"The \"fontFamily\" value is invalid. Valid values are font family names like: \"Arial\", \"Times New Roman\", etc. Make sure that the font family you are trying to use is installed on the server.");
}
[Fact]
public void AddImageWatermarkPreservesImageDimension()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
image.AddImageWatermark(watermark, horizontalAlign: "LEFT", verticalAlign: "top", opacity: 50, padding: 10);
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void CanAddTextAndImageWatermarks()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
image.AddImageWatermark(watermark, horizontalAlign: "LEFT", verticalAlign: "top", opacity: 30, padding: 10);
image.AddTextWatermark("plan9");
Assert.Equal(634, image.Width);
Assert.Equal(489, image.Height);
}
[Fact]
public void AddImageWatermarkDoesNotChangeWatermarkImage()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
image.AddImageWatermark(watermark, width: 54, height: 22, horizontalAlign: "LEFT", verticalAlign: "top", opacity: 50, padding: 10);
Assert.Equal(108, watermark.Width);
Assert.Equal(44, watermark.Height);
}
[Fact]
public void AddImageWatermarkThrowsOnNullImage()
{
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentNull(
() => image.AddImageWatermark(watermarkImage: null),
"watermarkImage");
}
[Fact]
public void AddImageWatermarkThrowsWhenJustOneDimensionIsZero()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
string message = "Watermark width and height must both be positive or both be zero.";
Assert.Throws<ArgumentException>(
() => image.AddImageWatermark(watermark, width: 0, height: 22), message);
Assert.Throws<ArgumentException>(
() => image.AddImageWatermark(watermark, width: 100, height: 0), message);
}
[Fact]
public void AddImageWatermarkThrowsWhenOpacityIsIncorrect()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentOutOfRange(() => image.AddImageWatermark(watermark, opacity: -1), "opacity", "Value must be between 0 and 100.");
Assert.ThrowsArgumentOutOfRange(() => image.AddImageWatermark(watermark, opacity: 120), "opacity", "Value must be between 0 and 100.");
}
[Fact]
public void AddImageWatermarkThrowsOnNegativeDimensions()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.AddImageWatermark(watermark, width: -1),
"width",
"0");
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.AddImageWatermark(watermark, height: -1),
"height",
"0");
}
[Fact]
public void AddImageWatermarkThrowsOnIncorrectHorizontalAlignment()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddImageWatermark(watermark, horizontalAlign: "horizontal"),
"The \"horizontalAlign\" value is invalid. Valid values are: \"Right\", \"Left\", and \"Center\".");
}
[Fact]
public void AddImageWatermarkThrowsOnIncorrectVerticalAlignment()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
Assert.Throws<ArgumentException>(
() => image.AddImageWatermark(watermark, verticalAlign: "vertical"),
"The \"verticalAlign\" value is invalid. Valid values are: \"Top\", \"Bottom\", and \"Middle\".");
}
[Fact]
public void AddImageWatermarkThrowsOnNegativePadding()
{
WebImage watermark = new WebImage(_BmpImageBytes);
WebImage image = new WebImage(_JpgImageBytes);
Assert.ThrowsArgumentGreaterThanOrEqualTo(
() => image.AddImageWatermark(watermark, padding: -10),
"padding",
"0");
}
[Fact]
public void AddImageWatermarkDoesNotChangeImageIfWatermarkIsTooBig()
{
WebImage watermark = new WebImage(_JpgImageBytes);
WebImage image = new WebImage(_BmpImageBytes);
byte[] originalBytes = image.GetBytes("jpg");
// This will use original watermark image dimensions which is bigger than the target image.
image.AddImageWatermark(watermark);
byte[] watermarkedBytes = image.GetBytes("jpg");
Assert.Equal(originalBytes, watermarkedBytes);
}
[Fact]
public void AddImageWatermarkWithFileNameThrowsExceptionWhenWatermarkDirectoryDoesNotExist()
{
var context = GetContext();
WebImage image = new WebImage(_BmpImageBytes);
Assert.Throws<DirectoryNotFoundException>(
() => image.AddImageWatermark(context, s => { throw new DirectoryNotFoundException(); }, @"x:\path\does\not\exist", width: 0, height: 0, horizontalAlign: "Right", verticalAlign: "Bottom", opacity: 100, padding: 5));
}
[Fact]
public void AddImageWatermarkWithFileNameThrowsExceptionWhenWatermarkFileDoesNotExist()
{
var context = GetContext();
WebImage image = new WebImage(_BmpImageBytes);
Assert.Throws<FileNotFoundException>(
() => image.AddImageWatermark(context, s => { throw new FileNotFoundException(); }, @"x:\there-is-no-file.jpg", width: 0, height: 0, horizontalAlign: "Right", verticalAlign: "Bottom", opacity: 100, padding: 5));
}
[Fact]
public void AddImageWatermarkWithFileNameThrowsExceptionWhenWatermarkFilePathIsNull()
{
var context = GetContext();
WebImage image = new WebImage(_BmpImageBytes);
Assert.ThrowsArgument(
() => image.AddImageWatermark(context, s => _JpgImageBytes, watermarkImageFilePath: null, width: 0, height: 0, horizontalAlign: "Right", verticalAlign: "Bottom", opacity: 100, padding: 5),
"filePath",
"Value cannot be null or an empty string.");
}
[Fact]
public void AddImageWatermarkWithFileNameThrowsExceptionWhenWatermarkFilePathIsEmpty()
{
var context = GetContext();
WebImage image = new WebImage(_BmpImageBytes);
Assert.ThrowsArgument(
() => image.AddImageWatermark(context, s => _JpgImageBytes, watermarkImageFilePath: null, width: 0, height: 0, horizontalAlign: "Right", verticalAlign: "Bottom", opacity: 100, padding: 5),
"filePath",
"Value cannot be null or an empty string.");
}
[Fact]
public void CanAddImageWatermarkWithFileName()
{
// Arrange
var context = GetContext();
WebImage image = new WebImage(_BmpImageBytes);
WebImage watermark = new WebImage(_JpgImageBytes);
// Act
var watermarkedWithImageArgument = image.AddImageWatermark(watermark).GetBytes();
var watermarkedWithFilePathArgument = image.AddImageWatermark(context, (name) => _JpgImageBytes, @"x:\jpegimage.jpg", width: 0, height: 0, horizontalAlign: "Right", verticalAlign: "Bottom", opacity: 100, padding: 5).GetBytes();
Assert.Equal(watermarkedWithImageArgument, watermarkedWithFilePathArgument);
}
[Fact]
public void SaveOverwritesExistingFile()
{
Action<string, byte[]> saveAction = (path, content) => { };
WebImage image = new WebImage(_BmpImageBytes);
string newFileName = @"x:\newImage.bmp";
image.Save(GetContext(), saveAction, newFileName, imageFormat: null, forceWellKnownExtension: true);
image.RotateLeft();
// just verify this does not throw
image.Save(GetContext(), saveAction, newFileName, imageFormat: null, forceWellKnownExtension: true);
}
[Fact]
public void SaveThrowsWhenPathIsNull()
{
Action<string, byte[]> saveAction = (path, content) => { };
// this constructor will not set path
byte[] originalContent = _BmpImageBytes;
WebImage image = new WebImage(originalContent);
Assert.ThrowsArgumentNullOrEmptyString(
() => image.Save(GetContext(), saveAction, filePath: null, imageFormat: null, forceWellKnownExtension: true),
"filePath");
}
[Fact]
public void SaveThrowsWhenPathIsEmpty()
{
Action<string, byte[]> saveAction = (path, content) => { };
WebImage image = new WebImage(_BmpImageBytes);
Assert.ThrowsArgumentNullOrEmptyString(
() => image.Save(GetContext(), saveAction, filePath: String.Empty, imageFormat: null, forceWellKnownExtension: true),
"filePath");
}
[Fact]
public void SaveUsesOriginalFormatWhenNoFormatIsSpecified()
{
// Arrange
// Use rooted path so we by pass using HttpContext
var specifiedOutputFile = @"C:\some-dir\foo.jpg";
string actualOutputFile = null;
Action<string, byte[]> saveAction = (fileName, content) => { actualOutputFile = fileName; };
// Act
WebImage image = new WebImage(_PngImageBytes);
image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: null, forceWellKnownExtension: true);
// Assert
Assert.Equal(Path.GetExtension(actualOutputFile), ".png");
}
[Fact]
public void SaveUsesOriginalFormatForStreamsWhenNoFormatIsSpecified()
{
// Arrange
// Use rooted path so we by pass using HttpContext
var specifiedOutputFile = @"x:\some-dir\foo.jpg";
string actualOutputFile = null;
Action<string, byte[]> saveAction = (fileName, content) => { actualOutputFile = fileName; };
// Act
WebImage image = new WebImage(_PngImageBytes);
image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: null, forceWellKnownExtension: true);
// Assert
Assert.Equal(Path.GetExtension(actualOutputFile), ".png");
}
[Fact]
public void SaveSetsExtensionBasedOnFormatWhenForceExtensionIsSet()
{
// Arrange
// Use rooted path so we by pass using HttpContext
var specifiedOutputFile = @"x:\some-dir\foo.exe";
string actualOutputFile = null;
Action<string, byte[]> saveAction = (fileName, content) => { actualOutputFile = fileName; };
// Act
WebImage image = new WebImage(_BmpImageBytes);
image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: "jpg", forceWellKnownExtension: true);
// Assert
Assert.Equal(".jpeg", Path.GetExtension(actualOutputFile));
Assert.Equal(specifiedOutputFile + ".jpeg", actualOutputFile);
}
[Fact]
public void SaveAppendsExtensionBasedOnFormatWhenForceExtensionIsSet()
{
// Arrange
// Use rooted path so we by pass using HttpContext
var specifiedOutputFile = @"x:\some-dir\foo";
string actualOutputFile = null;
Action<string, byte[]> saveAction = (fileName, content) => { actualOutputFile = fileName; };
// Act
WebImage image = new WebImage(_BmpImageBytes);
image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: "jpg", forceWellKnownExtension: true);
// Assert
Assert.Equal(".jpeg", Path.GetExtension(actualOutputFile));
}
[Fact]
public void SaveDoesNotModifyExtensionWhenExtensionIsCorrect()
{
// Arrange
// Use rooted path so we by pass using HttpContext
var specifiedOutputFile = @"x:\some-dir\foo.jpg";
string actualOutputFile = null;
Action<string, byte[]> saveAction = (fileName, content) => { actualOutputFile = fileName; };
// Act
WebImage image = new WebImage(_BmpImageBytes);
image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: "jpg", forceWellKnownExtension: true);
// Assert
Assert.Equal(specifiedOutputFile, actualOutputFile);
}
[Fact]
public void SaveDoesNotModifyExtensionWhenForceCorrectExtensionRenameIsCleared()
{
// Arrange
// Use rooted path so we by pass using HttpContext
var specifiedOutputFile = @"x:\some-dir\foo.exe";
string actualOutputFile = null;
Action<string, byte[]> saveAction = (fileName, content) => { actualOutputFile = fileName; };
// Act
WebImage image = new WebImage(_BmpImageBytes);
image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: "jpg", forceWellKnownExtension: false);
// Assert
Assert.Equal(specifiedOutputFile, actualOutputFile);
}
[Fact]
public void ImageFormatIsSavedCorrectly()
{
WebImage image = new WebImage(_BmpImageBytes);
Assert.Equal("bmp", image.ImageFormat);
}
[Fact]
public void SaveUsesInitialFormatWhenNoFormatIsSpecified()
{
// Arrange
string savePath = @"x:\some-dir\image.png";
MemoryStream stream = null;
Action<string, byte[]> saveAction = (path, content) => { stream = new MemoryStream(content); };
var image = new WebImage(_PngImageBytes);
// Act
image.FlipVertical().FlipHorizontal();
// Assert
image.Save(GetContext(), saveAction, savePath, imageFormat: null, forceWellKnownExtension: true);
using (Image savedImage = Image.FromStream(stream))
{
Assert.Equal(savedImage.RawFormat, ImageFormat.Png);
}
}
[Fact]
public void ImageFormatIsParsedCorrectly()
{
WebImage image = new WebImage(_BmpImageBytes);
Assert.Equal("bmp", image.ImageFormat);
}
private static HttpContextBase GetContext()
{
var httpContext = new Mock<HttpContextBase>();
var httpRequest = new Mock<HttpRequestBase>();
httpRequest.Setup(c => c.MapPath(It.IsAny<string>())).Returns((string path) => path);
httpContext.Setup(c => c.Request).Returns(httpRequest.Object);
return httpContext.Object;
}
// Test stream that pretends it can't seek.
private class TestStream : Stream
{
private MemoryStream _memoryStream;
public TestStream(MemoryStream memoryStream)
{
_memoryStream = memoryStream;
}
public override bool CanRead
{
get { return _memoryStream.CanRead; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return _memoryStream.CanWrite; }
}
public override void Flush()
{
_memoryStream.Flush();
}
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get { return _memoryStream.Position; }
set { _memoryStream.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return _memoryStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
_memoryStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
_memoryStream.Write(buffer, offset, count);
}
}
}
}