You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@reef.apache.org by Dhruv Mahajan <dh...@gmail.com> on 2016/10/04 05:54:35 UTC

Testing with background asynchronous functions C#

Hi

I am writing some REEF tests in C# for part of the code where there are
some asynchronous operations running continuously in the background. Now
for making sure that asynchronous functions finish their actions before I
check the results in the tests, I put some sleep in before I start
checking. Is there a way to avoid these sleeps altogether?

Thanks
Dhruv

Re: Testing with background asynchronous functions C#

Posted by Dhruv Mahajan <dh...@gmail.com>.
Yes it does...Thanks a lot.

Dhruv

On Tue, Oct 4, 2016 at 2:42 PM, Anupam <an...@gmail.com> wrote:

> This seems like a very generic question. :)
>
> There are multiple different tricks that can be done here.
>
> 1. Declare methods Task<Foo> such that you are able to perform a
> deterministic wait on the output of the method. Avoid background loops.
>
> 2. If there is a lifetime associated with every object instance of a class
> then you can create a public/internal property which returns a Task which
> indicates the state of the object.TaskCompletionSource helps a lot in such
> a pattern.
> Ex:
>
> public class Foo
> {
>
> public Task Completion {get {return taskCompletionSource.Task;}}
> private TaskCompletionSource<bool> taskCompletionSource;
> ...
>
> private void EndOfLife()
> {
>   if(exceptionHappened)
>   {
>     taskCompletionSource.SetException(e);
>   }
>   else
>   {
>     taskCompletionSource.SetResult(true);
>   }
> }
>
> }
>
> then you can wait on Completion in both production code or test to make
> deterministic decisions about the objects behavior wrt lifetime.
>
> 3. Even if you cannot do the same as 2. in the production code you could
> derive a TestFoo from Foo and wrap it with similar logic.
> Ex:
> public class TestObserver : MyObserver
> {
>   private MyObserver _inner;
>   private Task<bool> Completion => tcs.Task;
>   private TaskCompletionSource<bool> tcs;
>   public TestObserver(MyObserver ob)
>   {
>     _inner = ob;
>   }
>
>   public void OnNext()
>   {
>     try{
>     _inner.OnNext();
>     }
>     catch (e)
>     {
>       tcs.SetException(e);
>     }
>
>     tcs.SetResult(true);
>   }
> }
>
> ...
>
> public void MyTestMethod()
> {
>   var myobs = new MyObserver();
>   var testObs = new TestObserver(myobs);
> ... //more setup where we use testObs instead of myObs.
>   Assert.IsTrue(testObs.Completion.Wait(TimeSpan.FromSeconds(100))
> ...
> }
>
>
> 4. You can similarly use a ManualResetEvent/AutoResetEvent to mark
> completion of an async operation. This could be done specifically for
> testing purpose as well though should be avoided if possible.
> Ex:
>
> public class Foo
> {
>
> internal ManualResetEvent TestHook_mre_asyncjobfinished = new
> ManualResetEvent(false);
>
> public void SomethingAsync()
> {
> ...// async job
> TestHook_mre_asyncjobfinished.Set();
> }
>
> }
>
> public void MyTest()
> {
>
> var foo = new Foo();
> foo.SomethingAsync();
>
> foo.TestHook_mre_asyncjobfinished.WaitOne(TimeSpan.FromSeconds(20));
>
> //Assert on the outcome of the async operation;
>
> }
>
>
> Hope this helps.
>
> On 3 October 2016 at 22:54, Dhruv Mahajan <dh...@gmail.com> wrote:
>
> > Hi
> >
> > I am writing some REEF tests in C# for part of the code where there are
> > some asynchronous operations running continuously in the background. Now
> > for making sure that asynchronous functions finish their actions before I
> > check the results in the tests, I put some sleep in before I start
> > checking. Is there a way to avoid these sleeps altogether?
> >
> > Thanks
> > Dhruv
> >
>
>
>
> --
> Anupam
> Bellevue, WA
> Ph: +1 (425)-777-5570
>

Re: Testing with background asynchronous functions C#

Posted by Anupam <an...@gmail.com>.
This seems like a very generic question. :)

There are multiple different tricks that can be done here.

1. Declare methods Task<Foo> such that you are able to perform a
deterministic wait on the output of the method. Avoid background loops.

2. If there is a lifetime associated with every object instance of a class
then you can create a public/internal property which returns a Task which
indicates the state of the object.TaskCompletionSource helps a lot in such
a pattern.
Ex:

public class Foo
{

public Task Completion {get {return taskCompletionSource.Task;}}
private TaskCompletionSource<bool> taskCompletionSource;
...

private void EndOfLife()
{
  if(exceptionHappened)
  {
    taskCompletionSource.SetException(e);
  }
  else
  {
    taskCompletionSource.SetResult(true);
  }
}

}

then you can wait on Completion in both production code or test to make
deterministic decisions about the objects behavior wrt lifetime.

3. Even if you cannot do the same as 2. in the production code you could
derive a TestFoo from Foo and wrap it with similar logic.
Ex:
public class TestObserver : MyObserver
{
  private MyObserver _inner;
  private Task<bool> Completion => tcs.Task;
  private TaskCompletionSource<bool> tcs;
  public TestObserver(MyObserver ob)
  {
    _inner = ob;
  }

  public void OnNext()
  {
    try{
    _inner.OnNext();
    }
    catch (e)
    {
      tcs.SetException(e);
    }

    tcs.SetResult(true);
  }
}

...

public void MyTestMethod()
{
  var myobs = new MyObserver();
  var testObs = new TestObserver(myobs);
... //more setup where we use testObs instead of myObs.
  Assert.IsTrue(testObs.Completion.Wait(TimeSpan.FromSeconds(100))
...
}


4. You can similarly use a ManualResetEvent/AutoResetEvent to mark
completion of an async operation. This could be done specifically for
testing purpose as well though should be avoided if possible.
Ex:

public class Foo
{

internal ManualResetEvent TestHook_mre_asyncjobfinished = new
ManualResetEvent(false);

public void SomethingAsync()
{
...// async job
TestHook_mre_asyncjobfinished.Set();
}

}

public void MyTest()
{

var foo = new Foo();
foo.SomethingAsync();

foo.TestHook_mre_asyncjobfinished.WaitOne(TimeSpan.FromSeconds(20));

//Assert on the outcome of the async operation;

}


Hope this helps.

On 3 October 2016 at 22:54, Dhruv Mahajan <dh...@gmail.com> wrote:

> Hi
>
> I am writing some REEF tests in C# for part of the code where there are
> some asynchronous operations running continuously in the background. Now
> for making sure that asynchronous functions finish their actions before I
> check the results in the tests, I put some sleep in before I start
> checking. Is there a way to avoid these sleeps altogether?
>
> Thanks
> Dhruv
>



-- 
Anupam
Bellevue, WA
Ph: +1 (425)-777-5570