Skip to content

Instantly share code, notes, and snippets.

@manofstick
Created January 17, 2017 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manofstick/2be555566581c5057b460e53e113cdcd to your computer and use it in GitHub Desktop.
Save manofstick/2be555566581c5057b460e53e113cdcd to your computer and use it in GitHub Desktop.
A set of regression tests for lazy
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading;
using System.Reflection;
namespace LazyTest
{
[TestClass]
public class LazyRegressionTests
{
class MyException
: Exception
{
public int Value { get; }
public MyException(int value)
{
Value = value;
}
}
public class Simple
{
public int Value { get; }
public Simple(int value)
{
Value = value;
}
public Simple()
{
Value = 42;
}
}
public void SimpleInt(Lazy<int> lazy)
{
Assert.IsFalse(lazy.IsValueCreated);
Assert.AreEqual(lazy.Value, 42);
Assert.IsTrue(lazy.IsValueCreated);
}
[TestMethod]
public void SimpleInteger()
{
SimpleInt(new Lazy<int>(() => 42));
SimpleInt(new Lazy<int>(() => 42, true));
SimpleInt(new Lazy<int>(() => 42, false));
SimpleInt(new Lazy<int>(() => 42, LazyThreadSafetyMode.ExecutionAndPublication));
SimpleInt(new Lazy<int>(() => 42, LazyThreadSafetyMode.None));
SimpleInt(new Lazy<int>(() => 42, LazyThreadSafetyMode.PublicationOnly));
}
public void SimpleObject(Lazy<Simple> lazy)
{
Assert.IsFalse(lazy.IsValueCreated);
Assert.AreEqual(lazy.Value.Value, 42);
Assert.IsTrue(lazy.IsValueCreated);
}
[TestMethod]
public void SimpleObject()
{
SimpleObject(new Lazy<Simple>());
SimpleObject(new Lazy<Simple>(true));
SimpleObject(new Lazy<Simple>(false));
SimpleObject(new Lazy<Simple>(LazyThreadSafetyMode.ExecutionAndPublication));
SimpleObject(new Lazy<Simple>(LazyThreadSafetyMode.None));
SimpleObject(new Lazy<Simple>(LazyThreadSafetyMode.PublicationOnly));
SimpleObject(new Lazy<Simple>(() => new Simple(42)));
SimpleObject(new Lazy<Simple>(() => new Simple(42), true));
SimpleObject(new Lazy<Simple>(() => new Simple(42), false));
SimpleObject(new Lazy<Simple>(() => new Simple(42), LazyThreadSafetyMode.ExecutionAndPublication));
SimpleObject(new Lazy<Simple>(() => new Simple(42), LazyThreadSafetyMode.None));
SimpleObject(new Lazy<Simple>(() => new Simple(42), LazyThreadSafetyMode.PublicationOnly));
}
public void SimpleIntException(Lazy<int> lazy)
{
MyException e = null;
try
{
var _ = lazy.Value;
}
catch(MyException thrown)
{
e = thrown;
}
Assert.IsNotNull(e);
Assert.AreEqual(e.Value, 99);
}
[TestMethod]
[ExpectedException(typeof(MyException), "")]
public void SimpleIntegerException()
{
SimpleInt(new Lazy<int>(() => { throw new MyException(99); }));
SimpleInt(new Lazy<int>(() => { throw new MyException(99); }, true));
SimpleInt(new Lazy<int>(() => { throw new MyException(99); }, false));
SimpleInt(new Lazy<int>(() => { throw new MyException(99); }, LazyThreadSafetyMode.ExecutionAndPublication));
SimpleInt(new Lazy<int>(() => { throw new MyException(99); }, LazyThreadSafetyMode.None));
SimpleInt(new Lazy<int>(() => { throw new MyException(99); }, LazyThreadSafetyMode.PublicationOnly));
}
public class SimpleException
{
public SimpleException() : this(99) { }
public SimpleException(int value)
{
throw new MyException(value);
}
}
public void SimpleObjectException(Lazy<SimpleException> lazy)
{
TargetInvocationException e = null;
try
{
var _ = lazy.Value;
}
catch (TargetInvocationException ex)
{
e = ex;
}
Assert.IsNotNull(e);
}
[TestMethod]
[ExpectedException(typeof(MyException), "")]
public void SimpleObjectException()
{
SimpleObjectException(new Lazy<SimpleException>());
SimpleObjectException(new Lazy<SimpleException>(true));
SimpleObjectException(new Lazy<SimpleException>(false));
SimpleObjectException(new Lazy<SimpleException>(LazyThreadSafetyMode.ExecutionAndPublication));
SimpleObjectException(new Lazy<SimpleException>(LazyThreadSafetyMode.None));
SimpleObjectException(new Lazy<SimpleException>(LazyThreadSafetyMode.PublicationOnly));
SimpleObjectException(new Lazy<SimpleException>(() => new SimpleException(99)));
SimpleObjectException(new Lazy<SimpleException>(() => new SimpleException(99), true));
SimpleObjectException(new Lazy<SimpleException>(() => new SimpleException(99), false));
SimpleObjectException(new Lazy<SimpleException>(() => new SimpleException(99), LazyThreadSafetyMode.ExecutionAndPublication));
SimpleObjectException(new Lazy<SimpleException>(() => new SimpleException(99), LazyThreadSafetyMode.None));
SimpleObjectException(new Lazy<SimpleException>(() => new SimpleException(99), LazyThreadSafetyMode.PublicationOnly));
}
public void SameException<T>(Lazy<T> x)
{
Exception first = null;
try
{
var _ = x.Value;
}
catch (Exception thrown1)
{
first = thrown1;
}
Assert.IsNotNull(first);
try
{
var _ = x.Value;
}
catch (MyException thrown2)
{
Assert.AreSame(first, thrown2);
}
}
public void DifferentException<T>(Lazy<T> x)
{
Exception first = null;
try
{
var _ = x.Value;
}
catch (Exception thrown1)
{
first = thrown1;
}
Assert.IsNotNull(first);
Exception second = null;
try
{
var _ = x.Value;
}
catch (Exception thrown2)
{
second = thrown2;
}
Assert.IsNotNull(second);
Assert.AreNotEqual(first, second);
}
[TestMethod]
public void SameException()
{
SameException(new Lazy<int>(() => { throw new MyException(99); }));
SameException(new Lazy<int>(() => { throw new MyException(99); }, true));
SameException(new Lazy<int>(() => { throw new MyException(99); }, false));
SameException(new Lazy<int>(() => { throw new MyException(99); }, LazyThreadSafetyMode.ExecutionAndPublication));
SameException(new Lazy<int>(() => { throw new MyException(99); }, LazyThreadSafetyMode.None));
DifferentException(new Lazy<int>(() => { throw new MyException(99); }, LazyThreadSafetyMode.PublicationOnly));
DifferentException(new Lazy<SimpleException>());
DifferentException(new Lazy<SimpleException>(true));
DifferentException(new Lazy<SimpleException>(false));
DifferentException(new Lazy<SimpleException>(LazyThreadSafetyMode.ExecutionAndPublication));
DifferentException(new Lazy<SimpleException>(LazyThreadSafetyMode.None));
DifferentException(new Lazy<SimpleException>(LazyThreadSafetyMode.PublicationOnly));
SameException(new Lazy<SimpleException>(() => new SimpleException(99)));
SameException(new Lazy<SimpleException>(() => new SimpleException(99), true));
SameException(new Lazy<SimpleException>(() => new SimpleException(99), false));
SameException(new Lazy<SimpleException>(() => new SimpleException(99), LazyThreadSafetyMode.ExecutionAndPublication));
SameException(new Lazy<SimpleException>(() => new SimpleException(99), LazyThreadSafetyMode.None));
DifferentException(new Lazy<SimpleException>(() => new SimpleException(99), LazyThreadSafetyMode.PublicationOnly));
}
public void MultipleInt(Lazy<int> lazy, ref int counter, int expected)
{
counter = 0;
var result = 0;
for (var i=0; i < 10; ++i)
{
try { result = lazy.Value; } catch (Exception) { }
}
Assert.AreEqual(result, expected);
}
[TestMethod]
public void Multiple()
{
var counter = 0;
var f = new Func<int>(() => { if (++counter < 5) throw new MyException(42); else return counter; });
MultipleInt(new Lazy<int>(f), ref counter, 0);
MultipleInt(new Lazy<int>(f, true), ref counter, 0);
MultipleInt(new Lazy<int>(f, false), ref counter, 0);
MultipleInt(new Lazy<int>(f, LazyThreadSafetyMode.ExecutionAndPublication), ref counter, 0);
MultipleInt(new Lazy<int>(f, LazyThreadSafetyMode.None), ref counter, 0);
MultipleInt(new Lazy<int>(f, LazyThreadSafetyMode.PublicationOnly), ref counter, 5);
}
public void MultipleObject(Lazy<Simple> lazy, ref int counter, int? expected)
{
counter = 0;
var result = default(Simple);
for (var i = 0; i < 10; ++i)
{
try { result = lazy.Value; } catch (Exception) { }
}
if (expected == null)
Assert.IsNull(result);
else
Assert.AreEqual(result.Value, expected.Value);
}
[TestMethod]
public void MultipleObject()
{
var counter = 0;
var f = new Func<Simple>(() => { if (++counter < 5) throw new MyException(42); else return new Simple(counter); });
MultipleObject(new Lazy<Simple>(f), ref counter, null);
MultipleObject(new Lazy<Simple>(f, true), ref counter, null);
MultipleObject(new Lazy<Simple>(f, false), ref counter, null);
MultipleObject(new Lazy<Simple>(f, LazyThreadSafetyMode.ExecutionAndPublication), ref counter, null);
MultipleObject(new Lazy<Simple>(f, LazyThreadSafetyMode.None), ref counter, null);
MultipleObject(new Lazy<Simple>(f, LazyThreadSafetyMode.PublicationOnly), ref counter, 5);
}
class SimpleConstructor
{
public static int counter = 0;
public static int getValue()
{
if (++counter < 5)
throw new MyException(42);
else
return counter;
}
public int Value { get; }
public SimpleConstructor()
{
Value = getValue();
}
}
void MultipleObject(Lazy<SimpleConstructor> lazy, int? expected)
{
SimpleConstructor.counter = 0;
var result = default(SimpleConstructor);
for (var i = 0; i < 10; ++i)
{
try { result = lazy.Value; } catch (Exception) { }
}
if (expected == null)
Assert.IsNull(result);
else
Assert.AreEqual(result.Value, expected.Value);
}
[TestMethod]
public void MultipleConstructorObject()
{
MultipleObject(new Lazy<SimpleConstructor>(), 5);
MultipleObject(new Lazy<SimpleConstructor>(true), 5);
MultipleObject(new Lazy<SimpleConstructor>(false), 5);
MultipleObject(new Lazy<SimpleConstructor>(LazyThreadSafetyMode.ExecutionAndPublication), 5);
MultipleObject(new Lazy<SimpleConstructor>(LazyThreadSafetyMode.None), 5);
MultipleObject(new Lazy<SimpleConstructor>(LazyThreadSafetyMode.PublicationOnly), 5);
}
public void CheckForInvalidOperationException<T>(ref Lazy<T> x, Lazy<T> lazy)
{
x = lazy;
var correct = false;
try
{
var _ = lazy.Value;
}
catch (InvalidOperationException)
{
correct = true;
}
Assert.IsTrue(correct);
}
[TestMethod]
public void Recursion()
{
Lazy<int> x = null;
Func<int> f = () => x.Value;
CheckForInvalidOperationException(ref x, new Lazy<int>(f));
CheckForInvalidOperationException(ref x, new Lazy<int>(f, true));
CheckForInvalidOperationException(ref x, new Lazy<int>(f, false));
CheckForInvalidOperationException(ref x, new Lazy<int>(f, LazyThreadSafetyMode.ExecutionAndPublication));
CheckForInvalidOperationException(ref x, new Lazy<int>(f, LazyThreadSafetyMode.None));
// this just hangs in current implementation
// CheckForInvalidOperationException(ref x, new Lazy<int>(f, LazyThreadSafetyMode.PublicationOnly));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment