Поиск по сайту:

Что нужно знать о фазз-тестировании и Go


Команда Go приняла предложение добавить в язык поддержку фазз-тестирования.

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

Что такое фазз-тестирование?

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

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

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

Тестирование программного обеспечения на Go

В качестве примера проверки функции Add() в add.go вы можете написать тесты в add_test.go путем импорта пакета "testing". и добавление функций тестирования в функцию, начинающуюся с TestXXX().

Учитывая этот код:

func Add(num1, num2 int) int {
}

В файле add_test.go у вас может быть следующий код для тестирования:

import "testing"

func TestAdd(t *testing.T) {
}

Запустите тест:

$ go test

Добавлена поддержка фазз-тестирования.

Команда Go приняла предложение добавить в язык поддержку фазз-тестирования для дальнейшего развития этих усилий. Это включает в себя добавление нового типа testing.F , добавление функций FuzzXXX() в файлы _test.go и запуск этих тестов. с опцией -fuzz добавляется в инструмент Go.

В файле add_test.go:

func FuzzAdd(f *testing.F) {
}

Запустите код:

$ go test -fuzz

На момент написания эта функция является экспериментальной , но она должна быть включена в версию 1.18. Кроме того, многие функции, такие как -keepfuzzing и -race на данный момент не поддерживаются. Команда Go недавно опубликовала руководство по фаззингу, которое стоит прочитать.

Получите новейшие функции с установкой gotip

Если вы полны энтузиазма и хотите опробовать эту функцию до ее официального выпуска, вы можете использовать gotip, который позволит вам протестировать будущие функции Go и оставить отзыв. Чтобы установить gotip, вы можете использовать команды ниже. После установки вы можете использовать утилиту gotip для компиляции и запуска программы вместо обычной утилиты go .

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


$ gotip version
go version devel go1.18-f009910 Thu Jan 6 16:22:21 2022 +0000 linux/amd64
$

Неоднозначные мнения в обществе

Фаззинг часто является предметом дискуссий в сообществе разработчиков программного обеспечения, и мы находим людей на обоих концах спектра. Некоторые считают это полезным методом поиска ошибок, особенно в области безопасности. Хотя, учитывая необходимые ресурсы (ЦП/память) для фаззинга, некоторые считают его пустой тратой или предпочитают другие методы. Это заметно даже в команде Го. Мы видим, как соучредитель Go Роб Пайк немного скептически относится к использованию фаззинга и его реализации в Go.

... Хотя фаззинг хорош для поиска определенных классов ошибок, он требует очень больших затрат ресурсов ЦП и хранилища, а соотношение затрат и выгод остается неясным. Меня беспокоит бесполезная трата энергии и заполнение репозиториев git шумом тестовых данных...

~Роб Пайк

Однако другой член команды безопасности Go, Фило Соттиле, выглядит весьма оптимистично по поводу добавления поддержки фаззинга в Go, также подкрепляя это некоторыми примерами, и хочет, чтобы это стало частью процесса разработки.

Мне нравится говорить, что фаззинг находит ошибки на полях. Вот почему мы как команда безопасности в этом заинтересованы: обнаруженные на грани ошибки — это те, которые не попадают в производство и не становятся уязвимостями. 

Мы хотим, чтобы фаззинг был частью процесса разработки, а не сборки или обеспечения безопасности: внесите изменения в соответствующий код…

~Фило Соттиле

Фаззинг в реальном мире

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

AFL  — еще один популярный фаззер, используемый для фаззинга программ, написанных на C/C++.

В прошлом также были доступны варианты фаззинга программ Go, один из них — go-fuzz , о котором Фило упоминает в своих комментариях на GitHub.

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

Зачем добавлять встроенную поддержку фаззинга в Go

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

Разработчики могут использовать такие инструменты, как go-fuzz или fzgo (построенные на основе go-fuzz), для решения некоторых своих задач. Однако каждое существующее решение требует больше работы, чем обычное тестирование Go, и в нем отсутствуют важные функции. Фазз-тестирование не должно быть более сложным или менее полным, чем другие типы тестирования Go (например, бенчмаркинг или модульное тестирование). Существующие решения добавляют дополнительные накладные расходы, например, специальные инструменты командной строки,

Фазз-инструменты

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

Статьи по данной тематике: