using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
using Amazon.Runtime;
using ThirdParty.MD5;
namespace AWSSDK_DotNet.IntegrationTests.Utils
{
public static class UtilityMethods
{
public const string SDK_TEST_PREFIX = "aws-net-sdk";
static string _accountId;
///
/// There is not a good way to get account id. This hack creates
/// a topic gets the account id out of the ARN and then deletes the topic.
///
public static string AccountId
{
get
{
if(_accountId == null)
{
var createRequest = new CreateTopicRequest
{
Name = "sdk-accountid-lookup" + DateTime.Now.Ticks
};
using(var snsClient = new AmazonSimpleNotificationServiceClient())
{
var response = snsClient.CreateTopic(createRequest);
var tokens = response.TopicArn.Split(':');
_accountId = tokens[4];
snsClient.DeleteTopic(new DeleteTopicRequest { TopicArn = response.TopicArn });
}
}
return _accountId;
}
}
public static AWSCredentials CreateTemporaryCredentials()
{
using (var sts = new Amazon.SecurityToken.AmazonSecurityTokenServiceClient())
{
var creds = sts.GetSessionToken().Credentials;
return creds;
}
}
public static Stream CreateStreamFromString(string s)
{
return CreateStreamFromString(s, new MemoryStream());
}
public static Stream CreateStreamFromString(string s, Stream stream)
{
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
public static string GetResourceText(string resourceName)
{
using (StreamReader reader = new StreamReader(GetResourceStream(resourceName)))
{
return reader.ReadToEnd();
}
}
public static Stream GetResourceStream(string resourceName)
{
Assembly assembly = typeof(UtilityMethods).Assembly;
var resource = FindResourceName(resourceName);
Stream stream = assembly.GetManifestResourceStream(resource);
return stream;
}
public static string FindResourceName(string partialName)
{
return FindResourceName(s => s.IndexOf(partialName, StringComparison.OrdinalIgnoreCase) >= 0).Single();
}
public static IEnumerable FindResourceName(Predicate match)
{
Assembly assembly = typeof(UtilityMethods).Assembly;
var allResources = assembly.GetManifestResourceNames();
foreach (var resource in allResources)
{
if (match(resource))
yield return resource;
}
}
///
/// Helper function to format a byte array into string
///
/// The data blob to process
/// If true, returns hex digits in lower case form
/// String version of the data
public static string ToHex(byte[] data, bool lowercase)
{
var sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sb.Append(data[i].ToString(lowercase ? "x2" : "X2", CultureInfo.InvariantCulture));
}
return sb.ToString();
}
public static byte[] ComputeSHA256(byte[] data)
{
return new SHA256CryptoServiceProvider().ComputeHash(data);
}
public static void CompareFiles(string file1, string file2)
{
byte[] file1MD5 = computeHash(file1);
byte[] file2MD5 = computeHash(file2);
Assert.AreEqual(file1MD5.Length, file2MD5.Length);
for (int i = 0; i < file1MD5.Length; i++)
{
Assert.AreEqual(file1MD5[i], file2MD5[i], "MD5 of files do not match");
}
}
private static byte[] computeHash(string file)
{
Stream fileStream = File.OpenRead(file);
byte[] fileMD5 = new MD5Managed().ComputeHash(fileStream);
fileStream.Close();
return fileMD5;
}
public static T WaitUntilSuccess(Func loadFunction, int sleepSeconds = 5, int maxWaitSeconds = 300)
{
T result = default(T);
WaitUntil(() =>
{
try
{
result = loadFunction();
return result != null;
}
catch
{
return false;
}
}, sleepSeconds, maxWaitSeconds);
return result;
}
public static void WaitUntilException(Action action, int sleepSeconds = 5, int maxWaitSeconds = 300)
{
WaitUntil(() =>
{
try
{
action();
return false;
}
catch (Exception e)
{
throw;
}
}, sleepSeconds, maxWaitSeconds);
}
public static void WaitUntilSuccess(Action action, int sleepSeconds = 5, int maxWaitSeconds = 300)
{
if (sleepSeconds < 0) throw new ArgumentOutOfRangeException("sleepSeconds");
WaitUntilSuccess(action, new ListSleeper(sleepSeconds * 1000), maxWaitSeconds);
}
public static void WaitUntilSuccess(Action action, ListSleeper sleeper, int maxWaitSeconds = 300)
{
WaitUntil(() =>
{
try
{
action();
return true;
}
catch
{
return false;
}
}, sleeper, maxWaitSeconds);
}
public static void WaitUntil(Func matchFunction, int sleepSeconds = 5, int maxWaitSeconds = 300)
{
if (sleepSeconds < 0) throw new ArgumentOutOfRangeException("sleepSeconds");
WaitUntil(matchFunction, new ListSleeper(sleepSeconds * 1000), maxWaitSeconds);
}
public static void WaitUntil(Func matchFunction, ListSleeper sleeper, int maxWaitSeconds = 300)
{
if (maxWaitSeconds < 0) throw new ArgumentOutOfRangeException("maxWaitSeconds");
var maxTime = TimeSpan.FromSeconds(maxWaitSeconds);
var endTime = DateTime.Now + maxTime;
while(DateTime.Now < endTime)
{
if (matchFunction())
return;
sleeper.Sleep();
}
throw new TimeoutException(string.Format("Wait condition was not satisfied for {0} seconds", maxWaitSeconds));
}
public static void WriteFile(string path, string contents)
{
string fullPath = Path.GetFullPath(path);
new DirectoryInfo(Path.GetDirectoryName(fullPath)).Create();
File.WriteAllText(fullPath, contents);
}
public static void GenerateFile(string path, long size)
{
string contents = GenerateTestContents(size);
WriteFile(path, contents);
}
public static string GenerateTestContents(long size)
{
StringBuilder sb = new StringBuilder();
for (long i = 0; i < size; i++)
{
char c = (char)('a' + (i % 26));
sb.Append(c);
}
string contents = sb.ToString();
return contents;
}
public static string GenerateName()
{
return GenerateName(SDK_TEST_PREFIX + "-");
}
public static string GenerateName(string name)
{
return name + new Random().Next();
}
public class ListSleeper
{
private int attempt;
private int[] millisecondsList;
public ListSleeper(params int[] millisecondsList)
{
if (millisecondsList.Length < 1)
throw new ArgumentException("There must be at least one sleep period in millisecondsList.");
attempt = 0;
this.millisecondsList = millisecondsList;
}
public void Sleep()
{
// if there are more attempts than array elements just keep using the last one
var index = Math.Min(attempt, millisecondsList.Length - 1);
Thread.Sleep(millisecondsList[index]);
attempt++;
}
///
/// Create a new exponential growth sleeper. The following sleeper will be created:
/// ListSleeper(500, 1000, 2000, 5000)
///
/// A new ListSleeper with exponential growth
public static ListSleeper Create()
{
return new ListSleeper(500, 1000, 2000, 5000);
}
}
}
}