/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using Amazon.Runtime;
using Amazon.Runtime.Internal;
using Amazon.Runtime.Internal.Util;
using Amazon.Util;
using AWSSDK_DotNet35.UnitTests.TestTools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Collections.Generic;
using System.Text;
namespace AWSSDK.UnitTests
{
[TestClass]
public class ChecksumTests
{
///
/// Test that the outermost function for calculating a checksum computes the correct value
///
[DataRow(CoreChecksumAlgorithm.SHA1, "", "2jmj7l5rSw0yVb/vlWAYkK/YBwk=")]
[DataRow(CoreChecksumAlgorithm.SHA1, "abc", "qZk+NkcGgWq6PiVxeFDCbJzQ2J0=")]
[DataRow(CoreChecksumAlgorithm.SHA1, "Hello world", "e1AsOh9IyGCa4hLN+2Od7jlnP14=")]
[DataRow(CoreChecksumAlgorithm.SHA256, "", "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")]
[DataRow(CoreChecksumAlgorithm.SHA256, "abc", "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=")]
[DataRow(CoreChecksumAlgorithm.SHA256, "Hello world", "ZOyIygCyaOW6GjVnihtTFtIS9PNmskdyMlNKiuyjfzw=")]
[DataRow(CoreChecksumAlgorithm.CRC32, "", "AAAAAA==")]
[DataRow(CoreChecksumAlgorithm.CRC32, "abc", "NSRBwg==")]
[DataRow(CoreChecksumAlgorithm.CRC32, "Hello world", "i9aeUg==")]
[DataRow(CoreChecksumAlgorithm.CRC32C, "", "AAAAAA==")]
[DataRow(CoreChecksumAlgorithm.CRC32C, "abc", "Nks/tw==")]
[DataRow(CoreChecksumAlgorithm.CRC32C, "Hello world", "crUfeA==")]
[DataTestMethod]
public void CalculateChecksumTest(CoreChecksumAlgorithm algorithm, string content, string expectedBase64Checksum)
{
var contentBytes = Encoding.Default.GetBytes(content);
var computedChecksum = Convert.ToBase64String(CryptoUtilFactory.GetChecksumInstance(algorithm).ComputeHash(contentBytes));
Assert.AreEqual(expectedBase64Checksum, computedChecksum);
}
///
/// Test the interaction between whether a checksum is required, whether
/// an algorithm is provided, and whether a precalculated checksum is provided
/// to verify that the correct checksum is calculated for the request.
///
[TestMethod]
[DataRow(false, CoreChecksumAlgorithm.NONE, "", "")] // Checksum not required and not selected, so no checksum
[DataRow(true, CoreChecksumAlgorithm.CRC32, "", "x-amz-checksum-crc32")] // Checksum required, checksum specified, so calculated
[DataRow(false, CoreChecksumAlgorithm.CRC32, "", "x-amz-checksum-crc32")] // Checksum not required, checksum specified so calculated anyway
[DataRow(true, CoreChecksumAlgorithm.NONE, "", "Content-MD5")] // Checksum required, no checksum specified, so fallback to MD5
[DataRow(true, CoreChecksumAlgorithm.NONE, "x-amz-checksum-crc32", "x-amz-checksum-crc32")] // Checksum required, but already set
[DataRow(true, CoreChecksumAlgorithm.SHA256, "x-amz-checksum-crc32", "x-amz-checksum-crc32")] // Checksum specified but another was set, still calculate it anyway.
public void TestRequestChecksumSelection(bool fallbackToMD5, CoreChecksumAlgorithm checksumAlgorithm, string originalHeaderKey, string expectedHeaderKey)
{
var mock = new Mock();
var headers = new Dictionary();
var request = mock.Object;
mock.SetupGet(x => x.Headers).Returns(headers);
mock.SetupGet(x => x.Content).Returns(Encoding.ASCII.GetBytes("foo"));
if (!string.IsNullOrEmpty(originalHeaderKey))
{
headers.Add(originalHeaderKey, "foo");
}
ChecksumUtils.SetRequestChecksum(request, checksumAlgorithm.ToString(), fallbackToMD5);
if (!string.IsNullOrEmpty(expectedHeaderKey))
{
Assert.IsTrue(request.Headers.ContainsKey(expectedHeaderKey));
Assert.IsFalse(string.IsNullOrEmpty(request.Headers[expectedHeaderKey]));
}
else
{
Assert.AreEqual(0, request.Headers.Count);
}
}
[TestMethod]
public void ResponseChecksumSelection_NoChecksumsReturned()
{
var operationSupportedChecksums = new List
{
CoreChecksumAlgorithm.CRC32,
CoreChecksumAlgorithm.CRC32C
};
var responseData = new WebResponseData();
// No checksum headers on the response, so we cannot choose one to validate
Assert.AreEqual(CoreChecksumAlgorithm.NONE,
ChecksumUtils.SelectChecksumForResponseValidation(operationSupportedChecksums, responseData));
}
[TestMethod]
public void ResponseChecksumSelection_SingleChecksum()
{
var operationSupportedChecksums = new List
{
CoreChecksumAlgorithm.SHA256,
CoreChecksumAlgorithm.CRC32
};
var responseData = new WebResponseData();
responseData.Headers = new Dictionary
{
{ "x-amz-checksum-sha256", "checksum" }
};
// Even though CRC32 is supported and comes first in priority order, only SHA256 is returned from service
Assert.AreEqual(CoreChecksumAlgorithm.SHA256,
ChecksumUtils.SelectChecksumForResponseValidation(operationSupportedChecksums, responseData));
}
[TestMethod]
public void TestResponseChecksumSelection_Priority()
{
var operationSupportedChecksums = new List
{
CoreChecksumAlgorithm.SHA256,
CoreChecksumAlgorithm.CRC32
};
var responseData = new WebResponseData();
responseData.Headers = new Dictionary
{
{ "x-amz-checksum-sha256", "checksum" },
{ "x-amz-checksum-crc32", "checksum" }
};
// CRC32 should take priority over SHA256 when both are returned
Assert.AreEqual(CoreChecksumAlgorithm.CRC32,
ChecksumUtils.SelectChecksumForResponseValidation(operationSupportedChecksums, responseData));
}
[TestMethod]
public void TestResponseChecksumSelection_UnsupportedChecksum()
{
var operationSupportedChecksums = new List
{
CoreChecksumAlgorithm.SHA256,
CoreChecksumAlgorithm.CRC32
};
var responseData = new WebResponseData();
responseData.Headers = new Dictionary
{
{ "x-amz-checksum-crc64", "checksum" }
};
// CRC64 is not currently supported by the SDK
Assert.AreEqual(CoreChecksumAlgorithm.NONE,
ChecksumUtils.SelectChecksumForResponseValidation(operationSupportedChecksums, responseData));
}
}
}