- PVSM.RU - https://www.pvsm.ru -

Некоторые программисты, когда слышат про статический анализ, говорят о том, что он им не нужен, так как весь их код покрыт юнит-тестами, и этого достаточно, чтобы выловить все ошибки. Мне попалась ошибка, найти которую с помощью юнит-тестов теоретически возможно, но если о ней не знать, то написать такой тест практически нереально.
Lucene.Net — это портированная с Java на C# популярная библиотека для полнотекстового поиска. Исходный код открыт и доступен на сайте проекта https://lucenenet.apache.org/ [1].
Так как этот проект развивается медленно, содержит не так много кода и используется во многих других проектах для полнотекстового поиска, то и наш анализатор нашёл всего пять подозрительных мест [1 [2]]. На большее я и не рассчитывал. Но одно из этих срабатываний показалось мне особенно интересным, и я решил рассказать о нём читателям нашего блога.
Есть у нас диагностика V3035 [3] о том, что вместо += можно по ошибке написать =+, где + будет унарным плюсом. Когда я делал её по аналогии с такой же диагностикой V588 [4], предназначенной для языка C++, я думал — разве можно так ошибиться в C#? В C++ ещё ладно — кто-то использует разные текстовые редакторы вместо IDE, в которых можно опечататься и не заметить ошибку. Но набирая текст в Visual Studio, которая автоматически выравнивает код после того, как поставил точку с запятой, как это можно пропустить? Оказывается, что можно. Такую ошибку я обнаружил в Lucene.Net. А интересна она больше потому, что обнаружить её другими способами кроме статического анализа довольно сложно. Рассмотрим код:
protected virtual void Substitute( StringBuilder buffer )
{
substCount = 0;
for ( int c = 0; c < buffer.Length; c++ )
{
....
// Take care that at least one character
// is left left side from the current one
if ( c < buffer.Length - 1 )
{
// Masking several common character combinations
// with an token
if ( ( c < buffer.Length - 2 ) && buffer[c] == 's' &&
buffer[c + 1] == 'c' && buffer[c + 2] == 'h' )
{
buffer[c] = '$';
buffer.Remove(c + 1, 2);
substCount =+ 2;
}
....
else if ( buffer[c] == 's' && buffer[c + 1] == 't' )
{
buffer[c] = '!';
buffer.Remove(c + 1, 1);
substCount++;
}
....
}
}
}
Есть класс GermanStemmer, который обрезает суффиксы у немецких слов, чтобы выделить общий корень. Работает он следующим образом: сначала метод Substitute заменяет разные хорошие сочетания букв на другие символы, чтобы не спутать их с суффиксом. Заменяются: 'sch' на '$', 'st' на '!' и так далее (это видно из примера кода). Причем количество символов, на которое такими заменами уменьшится длина слова, накапливается в переменной substCount. Дальше метод Strip отрезает лишние суффиксы, и в конце метод Resubstitute выполняет обратную замену: '$' на 'sch', '!' на 'st'. То есть если у нас, например, было слово kapitalistischen (капиталистический), то стеммер [5] отработает следующим образом: kapitalistischen => kapitali!i$en (Substitute) => kapitali!i$ (Strip) => kapitalistisch (Resubstitute).
Из-за этой опечатки в коде при замене 'sch' на '$' в переменную substCount будет присвоено значение 2, вместо того, чтобы увеличить substCount на 2. И такую ошибку довольно сложно найти другими методами, кроме как статическим анализом. Есть разработчики, которые говорят: зачем мне статический анализатор, если у меня есть юнит-тесты? Так вот, чтобы отловить такую ошибку тестами, нужно тестировать Lucene.Net на немецком тексте, используя GermanStemmer, в тестах должно индексироваться слово, которое содержит в себе сочетание 'sch' и ещё одно сочетание букв, для которого будет выполнена подстановка, причём оно должно присутствовать в слове перед 'sch', чтобы substCount был отличен от нуля к тому моменту, когда выполнится выражение substCount =+ 2. Довольно нетривиальная комбинация для теста, особенно когда не видишь ошибки.
Юнит-тесты и статический анализ — это не исключающие, а дополняющие друг друга методики разработки программного обеспечения [2 [6]]. Предлагаю скачать [7] статический анализатор PVS-Studio, проверить свои проекты и найти ошибки, которые не были обнаружены с помощью юнит-тестов.
Автор: PVS-Studio
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-2/114930
Ссылки в тексте:
[1] https://lucenenet.apache.org/: https://lucenenet.apache.org/
[2] 1: http://www.viva64.com/ru/b/0158/
[3] V3035: http://www.viva64.com/ru/d/0398/
[4] V588: http://www.viva64.com/ru/d/0192/
[5] стеммер: https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BC%D0%BC%D0%B8%D0%BD%D0%B3
[6] 2: http://www.viva64.com/ru/a/0080/
[7] скачать: http://www.viva64.com/ru/pvs-studio-download/
[8] Источник: https://habrahabr.ru/post/279221/
Нажмите здесь для печати.