The Go Blog

Тестирование с помощью Fuzzing теперь доступно на стадии Beta

Кэтрин Хокман и Джей Конрод
3 июня 2021

Мы рады объявить, что нативное тестирование с помощью fuzzing теперь готово к тестированию на стадии beta!

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

Для получения дополнительной информации о данной функции смотрите golang.org/s/draft-fuzzing-design .

Начало работы

Для начала работы можно выполнить следующие команды:

<code>$ go install golang.org/dl/gotip@latest
$ gotip download
</code>

Это соберет инструментарий Go из ветки master. После выполнения этих команд gotip может использоваться как замена команды go. Теперь можно запускать команды, такие как

<code>$ gotip test -fuzz=Fuzz
</code>

Написание fuzz-теста

Тест на фаззинг должен находиться в файле с расширением *_test.go в виде функции вида FuzzXxx. Эта функция должна принимать аргумент типа *testing.F, аналогично тому, как функция TestXxx принимает аргумент типа *testing.T.

Ниже приведён пример теста на фаззинг, который тестирует поведение пакета net/url.

<code>//go:build go1.18
// +build go1.18
package fuzz
import (
  "net/url"
  "reflect"
  "testing"
)
func FuzzParseQuery(f *testing.F) {
  f.Add("x=1&y=2")
  f.Fuzz(func(t *testing.T, queryStr string) {
    query, err := url.ParseQuery(queryStr)
    if err != nil {
      t.Skip()
    }
    queryStr2 := query.Encode()
    query2, err := url.ParseQuery(queryStr2)
    if err != nil {
      t.Fatalf("ParseQuery failed to decode a valid encoded query %s: %v", queryStr2, err)
    }
    if !reflect.DeepEqual(query, query2) {
      t.Errorf("ParseQuery gave different query after being encoded\nbefore: %v\nafter: %v", query, query2)
    }
  })
}
</code>

Более подробную информацию о фаззинге можно найти на pkg.go.dev, включая обзор фаззинга с использованием Go и документацию по новому типу testing.F.

Ожидания

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

Обратите внимание, что тестирование с использованием fuzz-подхода может потреблять много памяти и влиять на производительность вашей машины во время выполнения. Команда go test -fuzz по умолчанию запускает fuzz-тестирование в параллельных процессах, количество которых равно значению переменной $GOMAXPROCS. Вы можете уменьшить количество используемых процессов при fuzz-тестировании, явно задав флаг -parallel с помощью команды go test. Дополнительную информацию можно получить, ознакомившись с документацией по команде go test, выполнив команду gotip help testflag.

Также обратите внимание, что движок fuzz-тестирования записывает значения, расширяющие покрытие тестов, в каталог кэша fuzz-тестов внутри $GOCACHE/fuzz во время выполнения. В настоящее время нет ограничений на количество файлов или общего количества байтов, которые могут быть записаны в кэш fuzz-тестов, поэтому он может занимать значительное количество дискового пространства (например, несколько гигабайт). Очистить кэш fuzz-тестов можно с помощью команды gotip clean -fuzzcache.

Что дальше?

Эта функция станет доступной, начиная с Go 1.18.

Если вы столкнётесь с какими-либо проблемами или у вас появится идея для новой функции, пожалуйста, создайте запрос.

Для обсуждения и получения общего обратной связи по этой функции, вы также можете принять участие в #fuzzing канале в Gophers Slack.

Удачного fuzz-тестирования!

Следующая статья: The Go Collective on Stack Overflow
Предыдущая статья: Результаты опроса разработчиков Go 2020 года
Индекс блога

GoRu.dev Golang на русском

На сайте представлена адаптированная под русский язык документация языка программирования Golang