3

I've worked with concurrency, but I don't know any good way to test it.

I would want to know if there is any way to "force" Tasks to execute in an specific order to simulate tests cases.

For example:

  1. Client #1 makes a request
  2. Server starts retrieving data to Client #1
  3. Client #2 makes another request while the server is still responding to Client #1
  4. Assert << something >>

I have seen some people using custom TaskSchedulers. Does it make sense?

5
  • Why don't you simply await each request in turn? Commented Aug 18, 2014 at 11:05
  • I don't see how to specify something like "while the first operation is pending, start this other operation". Commented Aug 18, 2014 at 11:13
  • did some googling, basically comes down to multithreading, with starts and sleeps to force concurrency. There are entire books on the subject. Commented Aug 18, 2014 at 11:18
  • Calling an awaitable method without await will start it immediately and will proceed in the next calls when it hits an await. You can use Task.WaitAll(...) for the operations to be in parallel. Commented Aug 18, 2014 at 11:19
  • What you're looking for is Chess, a research project from Microsoft. Commented Aug 18, 2014 at 11:51

3 Answers 3

1

I had had that problem in several occurrences too. Eventually I have created a helper that can start a bunch of threads to execute concurrent actions. The helper provides synchronization primitives and logging mechanisms. Here is a code fragment from a unit test:

[Test] public void TwoCodeBlocksInParallelTest() { // This static method runs the provided Action delegates in parallel using threads CTestHelper.Run( c => { Thread.Sleep(1000); // Here should be the code to provide something CTestHelper.AddSequenceStep("Provide"); // We record a sequence step for the expectations after the test CTestHelper.SetEvent(); }, c => { CTestHelper.WaitEvent(); // We wait until we can consume what is provided CTestHelper.AddSequenceStep("Consume"); // We record a sequence step for the expectations after the test }, TimeSpan.FromSeconds(10)); // This is a timeout parameter, if the threads are deadlocked or take too long, the threads are terminated and a timeout exception is thrown // After Run() completes we can analyze if the recorded sequence steps are in the correct order Expect(CTestHelper.GetSequence(), Is.EqualTo(new[] { "Provide", "Consume" })); } 

It can be used to test client/server or synchronization in components or simply run a thread with a timeout. I'll continue to improve this in the next weeks. Here is the project page: Concurrency Testing Helper

Sign up to request clarification or add additional context in comments.

Comments

1

This shouldn't be too difficult to simulate using tasks:

private async Task DoSomeAsyncOperation() { // This is just to simulate some work, // replace this with a usefull call to the server await Task.Delay(3000); } 

Now, lets consume it:

public async Task TestServerLoad() { var firstTaskCall = DoSomeAsyncOperation(); await Task.Delay(1000); // Lets assume it takes about a second to execute work agains't the server var secondCall = DoSomeAsyncOperation(); await Task.WhenAll(firstTaskCall, secondCall); // Wait till both complete } 

Comments

0

This is basic producer-consumer problem in concurrency. If you want to test that case, just put a Thread.Sleep(100) to server which part responds consumers. In that way, your server will have a delay before sending response. And you can Invoke service request simply creating new threads in a loop.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.