Fabio Iotti
Fabio Iotti

Reputation: 1540

How to test blocking function?

How do I test if a function blocks indefinitely in a particular situation?

[Test]
public void BlockingTest()
{
    blockingFunction();    // this function halts execution indefinitely

    Assert.Fail("Execution not halted.");
}

Supposing blockingFunction() is a function waiting for something to happen, that should block execution until a particular event occurs, and the test supposes this event to never occurr.

EDIT: what I'm actually looking for is an elegant solution, possibly without having to explicitly wait a hardcoded time before reporting success.

Posting my current situation for reference:

[Test]
public void BlockTest() {
    BytesStream bs = new BytesStream();
    bs.Write(new byte[] { 1, 2 }, 0, 2);

    var buff2 = new byte[2];
    bs.Read(buff2, 0, 2);

    bool dataWritten = false;

    new Thread(() => {
        for(int i=0; i<100; i++)
            Thread.Sleep(0); // ensure the parent thread execute next line

        dataWritten = true;
        bs.Write(new byte[] { 3, 4 }, 0, 2);
    }).Start();

    Assert.AreNotEqual(0, bs.Read(buff2, 0, 2), "#1");

    if(!dataWritten)
        Assert.Fail("#2");

    Assert.AreEqual(new byte[] { 3, 4 }, buff2, "#3");
}

Upvotes: 0

Views: 757

Answers (4)

user877329
user877329

Reputation: 6220

One idea if you have a trigger that should wake up the call:

In thread a:

  1. Call the blocking function
  2. For one second or maybe a little bit more, consume 100 % CPU
  3. Let the thread return

In thread b:

  1. Use the OS API to find the running status of thread a. Verify that it is currently sleeping.
  2. Trigger the event that makes thread a return from the blocking function
  3. Use the OS API to find the running status of thread b. Verify that it is currently running
  4. Synchronize with thread a

Upvotes: 0

Servy
Servy

Reputation: 203829

How do I test if a function blocks indefinitely in a particular situation?

This is called the Halting Problem. It is provably impossible to solve.

Upvotes: 3

enzi
enzi

Reputation: 4165

You have already answered your question. Your test method will wait an indefinite amount of time and fail should the blockingFunction return any sooner. Just let it run and fix the code should it ever fail.


Now to answer the real problem here: what do you really want to test?

Is it actually a requirement that the blockingFunction blocks execution? I'd presume that if it would consume queue items without blocking execution, it'd be even better – but your fictional test would fail then.

In other words: I assume it's not important that your blockingFunction blocks, you should test business logic and not technical behavior, unless there is an actual use case.

Like if your consumer were to terminate if no item would be generated within t seconds, then you could wait for t seconds and fail if it returned any sooner.

If you wanted to test whether your consumer "wakes up" after being idle for a while, you could wait for n seconds and then generate an item. Fail it the consumer does something earlier, and fail if it doesn't consume after you generate your item.

Only you can truly answer this question, for we don't know what you actually want to test here. I hope I managed to spell that out in a helpful way.

Upvotes: 0

Sjips
Sjips

Reputation: 1258

Maybe let your function execute by a Threadpool object and see if it returns within a specified timespan, like this:

    [Test]
    public void BlockingTest()
    {
        AutoResetEvent ev = new AutoResetEvent(false);
        BlockingFunctionHelper(ev);    
        // specify time out in ms, thus here: wait 1 s
        Assert.IsTrue(ev.WaitOne(1000), "Execution not halted.");
        ev.Dispose();
    }

    private void BlockingFunctionHelper(AutoResetEvent ev)
    {
        ThreadPool.QueueUserWorkItem((e) =>
            {
                BlockingFunction(); // this function halts execution indefinitely
                ((AutoResetEvent) e).Set();
            }, ev);
    }

Upvotes: 1

Related Questions