Как проверить функцию блокировки?

1

Как проверить, блокирует ли функция неопределенно в конкретной ситуации?

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

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

Предположим, что blockingFunction() - это функция, ожидающая чего-то, что должно блокировать выполнение до тех пор, пока не произойдет определенное событие, и тест предполагает, что это событие никогда не произойдет.

EDIT: то, что я на самом деле ищу, - это элегантное решение, возможно, без явного ожидания жесткого времени до отчета об успехе.

Отправьте мою текущую ситуацию для справки:

[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");
}
  • 4
    Просто подождите бесконечное количество времени, и вы докажете, что оно никогда не вернулось. Я не думаю, что вы можете сделать это, но если вы можете объяснить больше о коде, может быть другой способ.
  • 0
    Упрощение: у меня есть очередь, производитель записывает некоторые данные в очередь, а потребитель читает их. Если производителя нет, потребителю придется ждать бесконечно. Я пропатчил тест, создав поток производителя и подождав несколько мгновений, прежде чем отправлять что-то в очередь, разблокируя потребителя. Я ищу более элегантное решение. Спасибо
Теги:
nunit

3 ответа

3
Лучший ответ

Как проверить, блокирует ли функция неопределенно в конкретной ситуации?

Это называется проблемой остановки. Это невозможно решить.

1

Возможно, пусть ваша функция будет выполняться объектом Threadpool и посмотреть, будет ли она возвращаться в указанный промежуток времени, например:

    [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);
    }
  • 0
    Это очень похоже на то, что я делаю сейчас, я ищу что-то более элегантное. Возможно, не блокируя выполнение теста более нескольких миллисекунд.
  • 0
    Если вы укажете ev.WaitOne(50, ...) то вы проверите, вернется ли функция в течение 50 мс. Я провел быструю проверку (используя сон 500 или 5000 мс) в BlockingFunction() с кодом в моем ответе, и, похоже, он проверяется правильно. Но я не знаю, как сделать его более элегантным. Сожалею.
Показать ещё 4 комментария
0

Вы уже ответили на свой вопрос. Ваш метод тестирования будет ждать неопределенное количество времени и сбой, если blockingFunction вернется раньше. Просто позвольте этому запустить и исправить код, если он когда-либо потерпит неудачу.


Теперь, чтобы ответить на настоящую проблему: что вы действительно хотите проверить?

Это на самом деле требование blockingFunction блокировки исполнения? Я предполагаю, что если он будет потреблять элементы очереди, не блокируя выполнение, это было бы еще лучше, но ваш вымышленный тест не удался бы тогда.

Другими словами: я предполагаю, что не важно, чтобы блоки blockingFunction блокировались, вы должны проверять бизнес-логику, а не техническое поведение, если только не существует фактического варианта использования.

Например, если ваш потребитель должен был прекратить работу, если в течение t секунд не будет создан какой-либо элемент, вы можете подождать t секунд и потерпеть неудачу, если он вернется раньше.

Если вы хотите проверить, будет ли ваш потребитель "просыпаться" после простоя какое-то время, вы можете подождать n секунд и затем сгенерировать элемент. Не удалось, что потребитель делает что-то раньше, и сбой, если он не потребляет после создания вашего товара.

Только вы действительно можете ответить на этот вопрос, потому что мы не знаем, что вы на самом деле хотите проверить здесь. Надеюсь, мне удалось это объяснить полезным образом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню