Skip to content

Commit

Permalink
Major cleanup of TestUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
anaisbetts committed Mar 27, 2012
1 parent cec9f8b commit 9c7f0d0
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 73 deletions.
100 changes: 48 additions & 52 deletions ReactiveUI.Testing/TestUtils.cs
Expand Up @@ -38,6 +38,28 @@ public static IDisposable WithScheduler(IScheduler sched)
});
}

/// <summary>
/// WithMessageBus allows you to override the default Message Bus
/// implementation until the object returned is disposed. If a
/// message bus is not specified, a default empty one is created.
/// </summary>
/// <param name="messageBus">The message bus to use, or null to create
/// a new one using the default implementation.</param>
/// <returns>An object that when disposed, restores the original
/// message bus.</returns>
public static IDisposable WithMessageBus(this IMessageBus messageBus)
{
var origMessageBus = RxApp.MessageBus;

Monitor.Enter(mbGate);
RxApp.MessageBus = messageBus ?? new MessageBus();
return Disposable.Create(() =>
{
RxApp.MessageBus = origMessageBus;
Monitor.Exit(mbGate);
});
}

/// <summary>
/// With is an extension method that uses the given scheduler as the
/// default Deferred and Taskpool schedulers for the given Func. Use
Expand All @@ -47,7 +69,8 @@ public static IDisposable WithScheduler(IScheduler sched)
/// <param name="sched">The scheduler to use.</param>
/// <param name="block">The function to execute.</param>
/// <returns>The return value of the function.</returns>
public static TRet With<TRet>(this IScheduler sched, Func<IScheduler, TRet> block)
public static TRet With<T, TRet>(this T sched, Func<T, TRet> block)
where T : IScheduler
{
TRet ret;
using (WithScheduler(sched)) {
Expand All @@ -62,87 +85,60 @@ public static TRet With<TRet>(this IScheduler sched, Func<IScheduler, TRet> bloc
/// </summary>
/// <param name="sched">The scheduler to use.</param>
/// <param name="block">The action to execute.</param>
public static void With(this IScheduler sched, Action<IScheduler> block)
public static void With<T>(this T sched, Action<T> block)
where T : IScheduler
{
sched.With(x => { block(x); return 0; });
}

/// <summary>
/// With is an extension method that uses the given scheduler as the
/// default Deferred and Taskpool schedulers for the given Func. Use
/// this to initialize objects that store the default scheduler (most
/// RxXaml objects).
/// Override the default Message Bus during the specified block.
/// </summary>
/// <param name="sched">The scheduler to use.</param>
/// <param name="messageBus">The message bus to use for the block.</param>
/// <param name="block">The function to execute.</param>
/// <returns>The return value of the function.</returns>
public static TRet With<TRet>(this TestScheduler sched, Func<TestScheduler, TRet> block)
public static TRet With<TRet>(this IMessageBus messageBus, Func<TRet> block)
{
TRet ret;
using (WithScheduler(sched)) {
ret = block(sched);
using (messageBus.WithMessageBus()) {
return block();
}
return ret;
}

/// <summary>
/// With is an extension method that uses the given scheduler as the
/// default Deferred and Taskpool schedulers for the given Action.
/// Override the default Message Bus during the specified block.
/// </summary>
/// <param name="messageBus">The message bus to use for the block.</param>
/// <param name="sched">The scheduler to use.</param>
/// <param name="block">The action to execute.</param>
public static void With(this TestScheduler sched, Action<TestScheduler> block)
public static void With(this IMessageBus messageBus, Action block)
{
sched.With(x => { block(x); return 0; });
using (messageBus.WithMessageBus()) {
block();
}
}

/// <summary>
/// WithMessageBus allows you to override the default Message Bus
/// implementation until the object returned is disposed. If a
/// message bus is not specified, a default empty one is created.
/// AdvanceToMs moves the TestScheduler to the specified time in
/// milliseconds.
/// </summary>
/// <param name="messageBus">The message bus to use, or null to create
/// a new one using the default implementation.</param>
/// <returns>An object that when disposed, restores the original
/// message bus.</returns>
public static IDisposable WithMessageBus(this TestScheduler sched, IMessageBus messageBus = null)
{
var origMessageBus = RxApp.MessageBus;

Monitor.Enter(mbGate);
RxApp.MessageBus = messageBus ?? new MessageBus();
return Disposable.Create(() =>
{
RxApp.MessageBus = origMessageBus;
Monitor.Exit(mbGate);
});
}

/// <summary>
/// WithMessageBus allows you to override the default Message Bus
/// implementation for a specified action. If a message bus is not
/// specified, a default empty one is created.
/// <param name="block">The action to execute.</param>
/// <param name="messageBus">The message bus to use, or null to create
/// a new one using the default implementation.</param>
public static void WithMessageBus(this TestScheduler sched, Action<IMessageBus> block, IMessageBus messageBus = null)
/// <param name="milliseconds">The time offset to set the TestScheduler
/// to, in milliseconds. Note that this is *not* additive or
/// incremental, it sets the time.</param>
public static void AdvanceToMs(this TestScheduler sched, double milliseconds)
{
messageBus = messageBus ?? new MessageBus();
using(var _ = sched.WithMessageBus(messageBus)) {
block(messageBus);
}
sched.AdvanceTo(sched.FromTimeSpan(TimeSpan.FromMilliseconds(milliseconds)));
}

/// <summary>
/// RunToMilliseconds moves the TestScheduler to the specified time in
/// AdvanceToMs moves the TestScheduler along by the specified time in
/// milliseconds.
/// </summary>
/// <param name="milliseconds">The time offset to set the TestScheduler
/// to, in milliseconds. Note that this is *not* additive or
/// incremental, it sets the time.</param>
public static void RunToMilliseconds(this TestScheduler sched, double milliseconds)
public static void AdvanceByMs(this TestScheduler sched, double milliseconds)
{
sched.AdvanceTo(sched.FromTimeSpan(TimeSpan.FromMilliseconds(milliseconds)));
sched.AdvanceBy(sched.FromTimeSpan(TimeSpan.FromMilliseconds(milliseconds)));
}

/// <summary>
Expand Down Expand Up @@ -200,4 +196,4 @@ public static long FromTimeSpan(this TestScheduler sched, TimeSpan span)
}
}

// vim: tw=120 ts=4 sw=4 et :
// vim: tw=120 ts=4 sw=4 et :
2 changes: 1 addition & 1 deletion ReactiveUI.Tests/ObservableAsPropertyHelperTest.cs
Expand Up @@ -95,7 +95,7 @@ public void OAPHShouldBeObservable()
var fixture = new ObservableAsPropertyHelper<string>(inputOaph.Select(x => x.ToString()),
result.Add, "0");
sched.RunToMilliseconds(500);
sched.AdvanceToMs(500);
new[] {"0", "5", "10", "15", "20"}.AssertAreEqual(result);
});
Expand Down
4 changes: 2 additions & 2 deletions ReactiveUI.Tests/ObservableAsyncMRUCacheTest.cs
Expand Up @@ -31,13 +31,13 @@ public void GetTest()
t.Start();
sched.Start();
sched.RunToMilliseconds(500);
sched.AdvanceToMs(500);
// NB: The Thread.Sleep is to let our other thread catch up
Thread.Sleep(100);
Assert.Equal(0, result);
sched.RunToMilliseconds(1200);
sched.AdvanceToMs(1200);
Thread.Sleep(100);
Assert.Equal(25, result);
Expand Down
4 changes: 2 additions & 2 deletions ReactiveUI.Tests/ObservedChangedMixinTest.cs
Expand Up @@ -33,7 +33,7 @@ public void GetValueShouldActuallyReturnTheValue()
foreach (var v in input) { fixture.IsOnlyOneWord = v; }
sched.RunToMilliseconds(1000);
sched.AdvanceToMs(1000);
input.AssertAreEqual(output);
input.AssertAreEqual(output2);
Expand Down Expand Up @@ -89,7 +89,7 @@ public void ValueTest()
foreach (var v in input) { fixture.IsOnlyOneWord = v; }
sched.RunToMilliseconds(1000);
sched.AdvanceToMs(1000);
input.AssertAreEqual(output);
input.AssertAreEqual(output2);
Expand Down
6 changes: 3 additions & 3 deletions ReactiveUI.Tests/ReactiveCollectionTest.cs
Expand Up @@ -237,13 +237,13 @@ public void CreateCollectionWithTimer()
ReactiveCollection<string> fixture;

fixture = input.ToObservable(sched).CreateCollection(TimeSpan.FromSeconds(0.5));
sched.RunToMilliseconds(1005);
sched.AdvanceToMs(1005);
fixture.AssertAreEqual(input.Take(2));

sched.RunToMilliseconds(1505);
sched.AdvanceToMs(1505);
fixture.AssertAreEqual(input.Take(3));

sched.RunToMilliseconds(10000);
sched.AdvanceToMs(10000);
fixture.AssertAreEqual(input);
}
}
Expand Down
26 changes: 13 additions & 13 deletions ReactiveUI.Tests/ReactiveCommandTest.cs
Expand Up @@ -57,7 +57,7 @@ public void ObservableCanExecuteShouldShowUpInCommand()
// N.B. We check against '5' instead of 6 because we're supposed to
// suppress changes that aren't actually changes i.e. false => false
sched.RunToMilliseconds(10 * 1000);
sched.AdvanceToMs(10 * 1000);
return changes_as_observable;
});

Expand Down Expand Up @@ -115,7 +115,7 @@ public void MultipleSubscribesShouldntResultInMultipleNotifications()
fixture.Where(x => ((int)x) % 2 == 0).Subscribe(x => even_list.Add((int)x));

input.Run(x => fixture.Execute(x));
sched.RunToMilliseconds(1000);
sched.AdvanceToMs(1000);

new[]{1,1}.AssertAreEqual(odd_list);
new[]{2,2}.AssertAreEqual(even_list);
Expand Down Expand Up @@ -196,14 +196,14 @@ public void RegisterAsyncFunctionSmokeTest()
Observable.Return(5).Delay(TimeSpan.FromSeconds(5), sched)).CreateCollection();
var inflightResults = fixture.ItemsInflight.CreateCollection();
sched.RunToMilliseconds(10);
sched.AdvanceToMs(10);
Assert.True(fixture.CanExecute(null));
fixture.Execute(null);
sched.RunToMilliseconds(1005);
sched.AdvanceToMs(1005);
Assert.False(fixture.CanExecute(null));
sched.RunToMilliseconds(5100);
sched.AdvanceToMs(5100);
Assert.True(fixture.CanExecute(null));
new[] {0,1,0}.AssertAreEqual(inflightResults);
Expand Down Expand Up @@ -264,10 +264,10 @@ public void MultipleSubscribersShouldntDecrementRefcountBelowZero()
Assert.True(fixture.CanExecute(null));
fixture.Execute(null);
sched.RunToMilliseconds(2000);
sched.AdvanceToMs(2000);
Assert.False(fixture.CanExecute(null));
sched.RunToMilliseconds(6000);
sched.AdvanceToMs(6000);
Assert.True(fixture.CanExecute(null));
Assert.True(results.Count == 1);
Expand Down Expand Up @@ -373,36 +373,36 @@ public void CanExecuteShouldChangeOnInflightOp()
// CanExecute should be true, both input observable is true
// and we don't have anything inflight
sched.RunToMilliseconds(10);
sched.AdvanceToMs(10);
Assert.True(fixture.CanExecute(1));
Assert.True(latestCanExecute);
// Invoke a command 10ms in
fixture.Execute(1);
// At 300ms, input is false
sched.RunToMilliseconds(300);
sched.AdvanceToMs(300);
Assert.False(fixture.CanExecute(1));
Assert.False(latestCanExecute);
// At 600ms, input is true, but the command is still running
sched.RunToMilliseconds(600);
sched.AdvanceToMs(600);
Assert.False(fixture.CanExecute(1));
Assert.False(latestCanExecute);
// After we've completed, we should still be false, since from
// 750ms-1000ms the input observable is false
sched.RunToMilliseconds(900);
sched.AdvanceToMs(900);
Assert.False(fixture.CanExecute(1));
Assert.False(latestCanExecute);
Assert.Equal(-1, calculatedResult);
sched.RunToMilliseconds(1010);
sched.AdvanceToMs(1010);
Assert.True(fixture.CanExecute(1));
Assert.True(latestCanExecute);
Assert.Equal(calculatedResult, 5);
sched.RunToMilliseconds(1200);
sched.AdvanceToMs(1200);
Assert.False(fixture.CanExecute(1));
Assert.False(latestCanExecute);
});
Expand Down

0 comments on commit 9c7f0d0

Please sign in to comment.