Commit 2c76086f authored by Marc Gravell's avatar Marc Gravell

Booksleeve test suite: Batches, Performance, Program

parent 5b5d43cc
//using NUnit.Framework;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//namespace Tests
//{
// [TestFixture]
// public class Batches
// {
// [Test]
// public void TestBatchNotSent()
// {
// using (var conn = Config.GetUnsecuredConnection())
// {
// conn.Keys.Remove(0, "batch");
// conn.Strings.Set(0, "batch", "batch-not-sent");
// var tasks = new List<Task>();
// using (var batch = conn.CreateBatch())
// {
// tasks.Add(batch.Keys.Remove(0, "batch"));
// tasks.Add(batch.Sets.Add(0, "batch", "a"));
// tasks.Add(batch.Sets.Add(0, "batch", "b"));
// tasks.Add(batch.Sets.Add(0, "batch", "c"));
// }
// Assert.AreEqual("batch-not-sent", conn.Wait(conn.Strings.GetString(0, "batch")));
// }
// }
namespace Tests
{
[TestFixture]
public class Batches
{
[Test]
public void TestBatchNotSent()
{
using (var muxer = Config.GetUnsecuredConnection())
{
var conn = muxer.GetDatabase(0);
conn.KeyDeleteAsync("batch");
conn.StringSetAsync("batch", "batch-not-sent");
var tasks = new List<Task>();
var batch = conn.CreateBatch();
tasks.Add(batch.KeyDeleteAsync("batch"));
tasks.Add(batch.SetAddAsync("batch", "a"));
tasks.Add(batch.SetAddAsync("batch", "b"));
tasks.Add(batch.SetAddAsync("batch", "c"));
// [Test]
// public void TestBatchSentTogether()
// {
// TestBatchSent(true);
// }
// [Test]
// public void TestBatchSentApart()
// {
// TestBatchSent(false);
// }
// private void TestBatchSent(bool together)
// {
// using (var conn = Config.GetUnsecuredConnection())
// {
// conn.Keys.Remove(0, "batch");
// conn.Strings.Set(0, "batch", "batch-sent");
// var tasks = new List<Task>();
// using (var batch = conn.CreateBatch())
// {
// tasks.Add(batch.Keys.Remove(0, "batch"));
// tasks.Add(batch.Sets.Add(0, "batch", "a"));
// tasks.Add(batch.Sets.Add(0, "batch", "b"));
// tasks.Add(batch.Sets.Add(0, "batch", "c"));
// batch.Send(together);
// }
// var result = conn.Sets.GetAllString(0, "batch");
// tasks.Add(result);
// Task.WhenAll(tasks.ToArray());
Assert.AreEqual("batch-not-sent", (string)conn.StringGet("batch"));
}
}
// var arr = result.Result;
// Array.Sort(arr);
// Assert.AreEqual(3, arr.Length);
// Assert.AreEqual("a", arr[0]);
// Assert.AreEqual("b", arr[1]);
// Assert.AreEqual("c", arr[2]);
// }
// }
// }
//}
[Test]
public void TestBatchSent()
{
using (var muxer = Config.GetUnsecuredConnection())
{
var conn = muxer.GetDatabase(0);
conn.KeyDeleteAsync("batch");
conn.StringSetAsync("batch", "batch-sent");
var tasks = new List<Task>();
var batch = conn.CreateBatch();
tasks.Add(batch.KeyDeleteAsync("batch"));
tasks.Add(batch.SetAddAsync("batch", "a"));
tasks.Add(batch.SetAddAsync("batch", "b"));
tasks.Add(batch.SetAddAsync("batch", "c"));
batch.Execute();
var result = conn.SetMembersAsync("batch");
tasks.Add(result);
Task.WhenAll(tasks.ToArray());
var arr = result.Result;
Array.Sort(arr, (x, y) => string.Compare(x, y));
Assert.AreEqual(3, arr.Length);
Assert.AreEqual("a", (string)arr[0]);
Assert.AreEqual("b", (string)arr[1]);
Assert.AreEqual("c", (string)arr[2]);
}
}
}
}
//using System;
//using System.Diagnostics;
//using System.Text;
//using System.Threading.Tasks;
//using NUnit.Framework;
using System;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using StackExchange.Redis;
//namespace Tests
//{
// [TestFixture]
// public class Performance
// {
// [Test]
// public void VerifyPerformanceImprovement()
// {
// int asyncTimer, sync, op = 0, asyncFaF, syncFaF;
// using (var conn = Config.GetUnsecuredConnection())
// {
// // do these outside the timings, just to ensure the core methods are JITted etc
// for (int db = 0; db < 5; db++ )
// conn.Keys.Remove(db, "perftest");
namespace Tests
{
[TestFixture]
public class Performance
{
[Test]
public void VerifyPerformanceImprovement()
{
int asyncTimer, sync, op = 0, asyncFaF, syncFaF;
using (var muxer= Config.GetUnsecuredConnection())
{
// do these outside the timings, just to ensure the core methods are JITted etc
for (int db = 0; db < 5; db++)
{
muxer.GetDatabase(db).KeyDeleteAsync("perftest");
}
// var timer = Stopwatch.StartNew();
// for (int i = 0; i < 100; i++)
// {
// // want to test multiplex scenario; test each db, but to make it fair we'll
// // do in batches of 10 on each
// for (int db = 0; db < 5; db++)
// for (int j = 0; j < 10; j++)
// conn.Strings.Increment(db, "perftest");
// }
// asyncFaF = (int)timer.ElapsedMilliseconds;
// Task<string>[] final = new Task<string>[5];
// for (int db = 0; db < 5; db++)
// final[db] = conn.Strings.GetString(db, "perftest");
// conn.WaitAll(final);
// timer.Stop();
// asyncTimer = (int)timer.ElapsedMilliseconds;
// Console.WriteLine("async to completion (local): {0}ms", timer.ElapsedMilliseconds);
// for (int db = 0; db < 5; db++)
// Assert.AreEqual("1000", final[db].Result, "async, db:" + db);
// }
// using (var conn = new Redis(Config.LocalHost, 6379))
// {
// // do these outside the timings, just to ensure the core methods are JITted etc
// for (int db = 0; db < 5; db++) {
// conn.Db = db;
// conn.Remove("perftest");
// }
var timer = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
// want to test multiplex scenario; test each db, but to make it fair we'll
// do in batches of 10 on each
for (int db = 0; db < 5; db++)
{
var conn = muxer.GetDatabase(db);
for (int j = 0; j < 10; j++)
conn.StringIncrementAsync("perftest");
}
}
asyncFaF = (int)timer.ElapsedMilliseconds;
Task<RedisValue>[] final = new Task<RedisValue>[5];
for (int db = 0; db < 5; db++)
final[db] = muxer.GetDatabase(db).StringGetAsync("perftest");
muxer.WaitAll(final);
timer.Stop();
asyncTimer = (int)timer.ElapsedMilliseconds;
Console.WriteLine("async to completion (local): {0}ms", timer.ElapsedMilliseconds);
for (int db = 0; db < 5; db++)
Assert.AreEqual(1000, (long)final[db].Result, "async, db:" + db);
}
// var timer = Stopwatch.StartNew();
// for (int i = 0; i < 100; i++)
// {
// // want to test multiplex scenario; test each db, but to make it fair we'll
// // do in batches of 10 on each
// for (int db = 0; db < 5; db++) {
// conn.Db = db;
// op++;
// for (int j = 0; j < 10; j++) {
// conn.Increment("perftest");
// op++;
// }
// }
// }
// syncFaF = (int)timer.ElapsedMilliseconds;
// string[] final = new string[5];
// for (int db = 0; db < 5; db++) {
// conn.Db = db;
// final[db] = Encoding.ASCII.GetString(conn.Get("perftest"));
// }
// timer.Stop();
// sync = (int)timer.ElapsedMilliseconds;
// Console.WriteLine("sync to completion (local): {0}ms", timer.ElapsedMilliseconds);
// for (int db = 0; db < 5; db++)
// Assert.AreEqual("1000", final[db], "async, db:" + db);
// }
// int effectiveAsync = ((10 * asyncTimer) + 3) / 10;
// int effectiveSync = ((10 * sync) + (op * 3)) / 10;
// Console.WriteLine("async to completion with assumed 0.3ms LAN latency: " + effectiveAsync);
// Console.WriteLine("sync to completion with assumed 0.3ms LAN latency: " + effectiveSync);
// Console.WriteLine("fire-and-forget: {0}ms sync vs {1}ms async ", syncFaF, asyncFaF);
// Assert.Less(effectiveAsync, effectiveSync, "Everything");
// Assert.Less(asyncFaF, syncFaF, "Fire and Forget");
// }
// }
//}
using (var conn = new Redis(Config.LocalHost, 6379))
{
// do these outside the timings, just to ensure the core methods are JITted etc
for (int db = 0; db < 5; db++)
{
conn.Db = db;
conn.Remove("perftest");
}
var timer = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
// want to test multiplex scenario; test each db, but to make it fair we'll
// do in batches of 10 on each
for (int db = 0; db < 5; db++)
{
conn.Db = db;
op++;
for (int j = 0; j < 10; j++)
{
conn.Increment("perftest");
op++;
}
}
}
syncFaF = (int)timer.ElapsedMilliseconds;
string[] final = new string[5];
for (int db = 0; db < 5; db++)
{
conn.Db = db;
final[db] = Encoding.ASCII.GetString(conn.Get("perftest"));
}
timer.Stop();
sync = (int)timer.ElapsedMilliseconds;
Console.WriteLine("sync to completion (local): {0}ms", timer.ElapsedMilliseconds);
for (int db = 0; db < 5; db++)
Assert.AreEqual("1000", final[db], "async, db:" + db);
}
int effectiveAsync = ((10 * asyncTimer) + 3) / 10;
int effectiveSync = ((10 * sync) + (op * 3)) / 10;
Console.WriteLine("async to completion with assumed 0.3ms LAN latency: " + effectiveAsync);
Console.WriteLine("sync to completion with assumed 0.3ms LAN latency: " + effectiveSync);
Console.WriteLine("fire-and-forget: {0}ms sync vs {1}ms async ", syncFaF, asyncFaF);
Assert.Less(effectiveAsync, effectiveSync, "Everything");
Assert.Less(asyncFaF, syncFaF, "Fire and Forget");
}
}
}
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using NUnit.Framework;
//using System.Reflection;
//using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.Reflection;
using System.Threading.Tasks;
//namespace Tests
//{
// class Program
// {
// static void Main()
// {
// try
// {
// Main2();
// }
// catch (Exception ex)
// {
// Console.WriteLine();
// Console.WriteLine("CRAZY ERRORS: " + ex);
// }
// finally
// {
// Console.WriteLine("Press any key to exit");
// Console.ReadKey();
// }
// }
// static void Main2() {
// // why is this here? because some dumbass forgot to install a decent test-runner before going to the airport
// var epicFail = new List<string>();
// var testTypes = from type in typeof(Program).Assembly.GetTypes()
// where Attribute.IsDefined(type, typeof(TestFixtureAttribute))
// && !Attribute.IsDefined(type, typeof(IgnoreAttribute))
// let methods = type.GetMethods()
// select new
// {
// Type = type,
// Methods = methods,
// ActiveMethods = methods.Where(x => Attribute.IsDefined(x, typeof(ActiveTestAttribute))).ToArray(),
// Setup = methods.SingleOrDefault(x => Attribute.IsDefined(x, typeof(TestFixtureSetUpAttribute))),
// TearDown = methods.SingleOrDefault(x => Attribute.IsDefined(x, typeof(TestFixtureTearDownAttribute)))
// };
// int pass = 0, fail = 0;
namespace Tests
{
class Program
{
static void Main()
{
try
{
Main2();
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("CRAZY ERRORS: " + ex);
}
finally
{
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
static void Main2()
{
// why is this here? because some dumbass forgot to install a decent test-runner before going to the airport
var epicFail = new List<string>();
var testTypes = from type in typeof(Program).Assembly.GetTypes()
where Attribute.IsDefined(type, typeof(TestFixtureAttribute))
&& !Attribute.IsDefined(type, typeof(IgnoreAttribute))
let methods = type.GetMethods()
select new
{
Type = type,
Methods = methods,
ActiveMethods = methods.Where(x => Attribute.IsDefined(x, typeof(ActiveTestAttribute))).ToArray(),
Setup = methods.SingleOrDefault(x => Attribute.IsDefined(x, typeof(TestFixtureSetUpAttribute))),
TearDown = methods.SingleOrDefault(x => Attribute.IsDefined(x, typeof(TestFixtureTearDownAttribute)))
};
int pass = 0, fail = 0;
// bool activeOnly = testTypes.SelectMany(x => x.ActiveMethods).Any();
bool activeOnly = testTypes.SelectMany(x => x.ActiveMethods).Any();
// TaskScheduler.UnobservedTaskException += (sender, args) =>
// {
// args.SetObserved();
// //if (args.Exception is AggregateException)
// //{
// // foreach (var ex in ((AggregateException)args.Exception).InnerExceptions)
// // {
// // Console.WriteLine(ex.Message);
// // }
// //}
// //else
// //{
// // Console.WriteLine(args.Exception.Message);
// //}
// };
TaskScheduler.UnobservedTaskException += (sender, args) =>
{
args.SetObserved();
//if (args.Exception is AggregateException)
//{
// foreach (var ex in ((AggregateException)args.Exception).InnerExceptions)
// {
// Console.WriteLine(ex.Message);
// }
//}
//else
//{
// Console.WriteLine(args.Exception.Message);
//}
};
// foreach (var type in testTypes)
// {
// var tests = (from method in (activeOnly ? type.ActiveMethods : type.Methods)
// where Attribute.IsDefined(method, typeof(TestAttribute))
// && !Attribute.IsDefined(method, typeof(IgnoreAttribute))
// select method).ToArray();
foreach (var type in testTypes)
{
var tests = (from method in (activeOnly ? type.ActiveMethods : type.Methods)
where Attribute.IsDefined(method, typeof(TestAttribute))
&& !Attribute.IsDefined(method, typeof(IgnoreAttribute))
select method).ToArray();
// if (tests.Length == 0) continue;
if (tests.Length == 0) continue;
// Console.WriteLine(type.Type.FullName);
// object obj;
// try
// {
// obj = Activator.CreateInstance(type.Type);
// if (obj == null) throw new InvalidOperationException("the world has gone mad");
// }
// catch (Exception ex)
// {
// Console.WriteLine(ex.Message);
// continue;
// }
// using (obj as IDisposable)
// {
// if (type.Setup != null)
// {
// try { type.Setup.Invoke(obj, null); }
// catch (Exception ex)
// {
// Console.WriteLine("Test fixture startup failed: " + ex.Message);
// fail++;
// epicFail.Add(type.Setup.DeclaringType.FullName + "." + type.Setup.Name);
// continue;
// }
// }
// foreach (var test in tests)
// {
// var expectedFail = Attribute.GetCustomAttribute(test, typeof(ExpectedExceptionAttribute)) as ExpectedExceptionAttribute;
// Console.Write(test.Name + ": ");
// Exception err = null;
Console.WriteLine(type.Type.FullName);
object obj;
try
{
obj = Activator.CreateInstance(type.Type);
if (obj == null) throw new InvalidOperationException("the world has gone mad");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
continue;
}
using (obj as IDisposable)
{
if (type.Setup != null)
{
try
{ type.Setup.Invoke(obj, null); }
catch (Exception ex)
{
Console.WriteLine("Test fixture startup failed: " + ex.Message);
fail++;
epicFail.Add(type.Setup.DeclaringType.FullName + "." + type.Setup.Name);
continue;
}
}
// try
// {
// int count = 1;
// if (activeOnly)
// {
// var ata = test.GetCustomAttribute(typeof(ActiveTestAttribute)) as ActiveTestAttribute;
// if (ata != null) count = ata.Count;
// }
// while (count-- > 0)
// {
// test.Invoke(obj, null);
// }
// }
// catch (TargetInvocationException ex)
// {
// err = ex.InnerException;
// }
// catch (Exception ex)
// {
// err = ex;
// }
foreach (var test in tests)
{
var expectedFail = Attribute.GetCustomAttribute(test, typeof(ExpectedExceptionAttribute)) as ExpectedExceptionAttribute;
Console.Write(test.Name + ": ");
Exception err = null;
// if (err is AggregateException && ((AggregateException)err).InnerExceptions.Count == 1)
// {
// err = ((AggregateException)err).InnerExceptions[0];
// }
try
{
int count = 1;
if (activeOnly)
{
var ata = test.GetCustomAttribute(typeof(ActiveTestAttribute)) as ActiveTestAttribute;
if (ata != null) count = ata.Count;
}
while (count-- > 0)
{
test.Invoke(obj, null);
}
}
catch (TargetInvocationException ex)
{
err = ex.InnerException;
}
catch (Exception ex)
{
err = ex;
}
// if (expectedFail != null)
// {
// if (err == null)
// {
// err = new NUnit.Framework.AssertionException("failed to fail");
// }
// else
// {
// int issues = 0;
// if (expectedFail.ExpectedException != null && !expectedFail.ExpectedException.IsAssignableFrom(err.GetType()))
// {
// issues++;
// }
// if (expectedFail.ExpectedExceptionName != null && err.GetType().FullName != expectedFail.ExpectedExceptionName)
// {
// issues++;
// }
// if (expectedFail.ExpectedMessage != null && err.Message != expectedFail.ExpectedMessage)
// {
// issues++;
// }
// if (issues == 0) err = null;
// else
// {
// err = new InvalidOperationException("Failed in a different way", err);
// }
// }
// }
if (err is AggregateException && ((AggregateException)err).InnerExceptions.Count == 1)
{
err = ((AggregateException)err).InnerExceptions[0];
}
// if (err == null)
// {
// Console.WriteLine("pass");
// pass++;
// }
// else
// {
// Console.WriteLine(err.Message);
// fail++;
// epicFail.Add(test.DeclaringType.FullName + "." + test.Name);
// }
// }
// if (type.TearDown != null)
// {
// try { type.TearDown.Invoke(obj, null); }
// catch (Exception ex)
// {
// Console.WriteLine("Test fixture teardown failed: " + ex.Message);
// fail++;
// epicFail.Add(type.TearDown.DeclaringType.FullName + "." + type.TearDown.Name);
// }
// }
// }
// }
// Console.WriteLine("Passed: {0}; Failed: {1}", pass, fail);
// foreach (var msg in epicFail) Console.WriteLine(msg);
//#if DEBUG
// Console.WriteLine();
// Console.WriteLine("Callbacks: {0:###,###,##0} sync, {1:###,###,##0} async",
// BookSleeve.RedisConnectionBase.AllSyncCallbacks, BookSleeve.RedisConnectionBase.AllAsyncCallbacks);
//#endif
// }
// }
//}
if (expectedFail != null)
{
if (err == null)
{
err = new NUnit.Framework.AssertionException("failed to fail");
}
else
{
int issues = 0;
if (expectedFail.ExpectedException != null && !expectedFail.ExpectedException.IsAssignableFrom(err.GetType()))
{
issues++;
}
if (expectedFail.ExpectedExceptionName != null && err.GetType().FullName != expectedFail.ExpectedExceptionName)
{
issues++;
}
if (expectedFail.ExpectedMessage != null && err.Message != expectedFail.ExpectedMessage)
{
issues++;
}
if (issues == 0) err = null;
else
{
err = new InvalidOperationException("Failed in a different way", err);
}
}
}
//[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
//public sealed class ActiveTestAttribute : Attribute {
// private readonly int count;
// public int Count { get { return count; } }
// public ActiveTestAttribute() : this(1) { }
// public ActiveTestAttribute(int count) { this.count = count; }
//}
\ No newline at end of file
if (err == null)
{
Console.WriteLine("pass");
pass++;
}
else
{
Console.WriteLine(err.Message);
fail++;
epicFail.Add(test.DeclaringType.FullName + "." + test.Name);
}
}
if (type.TearDown != null)
{
try
{ type.TearDown.Invoke(obj, null); }
catch (Exception ex)
{
Console.WriteLine("Test fixture teardown failed: " + ex.Message);
fail++;
epicFail.Add(type.TearDown.DeclaringType.FullName + "." + type.TearDown.Name);
}
}
}
}
Console.WriteLine("Passed: {0}; Failed: {1}", pass, fail);
foreach (var msg in epicFail) Console.WriteLine(msg);
#if DEBUG
Console.WriteLine();
Console.WriteLine("Callbacks: {0:###,###,##0} sync, {1:###,###,##0} async",
BookSleeve.RedisConnectionBase.AllSyncCallbacks, BookSleeve.RedisConnectionBase.AllAsyncCallbacks);
#endif
}
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class ActiveTestAttribute : Attribute
{
private readonly int count;
public int Count { get { return count; } }
public ActiveTestAttribute() : this(1) { }
public ActiveTestAttribute(int count) { this.count = count; }
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment