C#: Как протестировать на StackOverflowException

Скажите, что у Вас есть метод, который мог потенциально застрять в бесконечном цикле вызова метода и катастрофическом отказе с StackOverflowException. Например, мое наивное RecursiveSelect метод упоминается в этом вопросе.

Начиная с версии 2.0 Платформы.NET, объект StackOverflowException не может быть пойман блоком try-catch, и соответствующий процесс завершается по умолчанию. Следовательно, пользователям рекомендуют написать их код, чтобы обнаружить и предотвратить переполнение стека. Например, если Ваше приложение зависит от рекурсии, используйте счетчик или условие состояния завершить рекурсивный цикл.

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

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

18
задан Community 23 May 2017 в 12:08
поделиться

6 ответов

Нужно решить проблему Халтинга ! Это сделает тебя богатым и знаменитым :)

7
ответ дан 30 November 2019 в 09:14
поделиться

Как насчет проверки количества кадров на стеке в assert statement?

const int MaxFrameCount = 100000;
Debug.Assert(new StackTrace().FrameCount < MaxFrameCount);

В вашем примере из связанного с этим вопроса это было бы (Дорогостоящий assert statement будет удален в сборке релиза):

public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> subjects, Func<T, IEnumerable<T>> selector)
{
    const int MaxFrameCount = 100000;
    Debug.Assert(new StackTrace().FrameCount < MaxFrameCount);

    // Stop if subjects are null or empty
    if(subjects == null || !subjects.Any())
        yield break;

    // For each subject
    foreach(var subject in subjects)
    {
        // Yield it
        yield return subject;

        // Then yield all its decendants
        foreach (var decendant in SelectRecursive(selector(subject), selector))
            yield return decendant;
    }
}

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

3
ответ дан 30 November 2019 в 09:14
поделиться

Это зло, но вы можете раскрутить его в новом процессе. Запустите процесс из юнит-теста, дождитесь его завершения и проверьте результат.

2
ответ дан 30 November 2019 в 09:14
поделиться

В первую очередь я думаю, что метод должен с этим справиться и убедиться, что он не повторяется слишком глубоко.

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

0
ответ дан 30 November 2019 в 09:14
поделиться

Мы не можем провести тест StackOverflow, так как в такой ситуации, когда больше не осталось стека для выделения, приложение автоматически завершает работу.

1
ответ дан 30 November 2019 в 09:14
поделиться

Идея состоит в том, чтобы отслеживать, насколько глубоко вложена рекурсивная функция, чтобы она не занимала слишком много места в стеке. Пример:

string ProcessString(string s, int index) {
   if (index > 1000) return "Too deeply nested";
   s = s.Substring(0, index) + s.Substring(index, 1).ToUpper() + s.Substring(index + 1);
   return ProcessString(s, index + 1);
}

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

2
ответ дан 30 November 2019 в 09:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: