fzgen

module
v0.1.44 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 6, 2025 License: Apache-2.0

README

FzGen

Автоматически генерирует фаззинг цели для переданного пакета.

Установка

$ go install github.com/BelehovEgor/fzgen/cmd/fzgen@latest
$ go get github.com/BelehovEgor/fzgen/fuzzer

Настройки

[-ctor=] - Регулярное выражение, определяющее имя конструкторов, которые будут использоваться для создания типов данных пакета.

[-unexported] - В тестовом файле будут использоваться несэкспортированные структуры, функции.

[-mocks] [-mocksPackagePrefix] [-mocksDepth] - Набор флагов определяющий интеграцию с Mockery (который должен быть установлен для использования).

  • [-mocks] Включение моков в генерации.
  • [-mocksPackagePrefix=] Имя пакета, в котором лежит тестовый файл. Необходимо для правильной генерации импортов сгенерированных моков.
  • [-mocksDepth=] Максимальная глубина при генерации моков. (Если для генерации мока, требуется сгенерировать еще один мок - глубина увеличивается на 1) Default - 5.

[-structFillMode=] - Выбирает настройку заполнения структур

  • "Constructors" - если есть конструктор в приоритете выбирается конструктор для создания структуры
  • "Random" - заполнение структур по полям
  • "ConstructorsAndRandom" - случайно выбирает как заполнять структуру

[-fillUnexported] - Включает возможность заполнять несэкспортированные поля в структурах.

[-llm=] - Включает интеграцию с LLM. Сейчас реализованы интеграции с openrouter, groq, gigachat

  • "openrouter"
  • "gigachat"
  • "groq-qwen"
  • "groq-deepseek"

Для использования данных интеграций необходимо указать креды через переменные окружения:

  • openrouter_api_key
  • gigachat_api_key
  • groq_api_key

Для задержки между запросами - переменная timeout - в секундах указывает паузу между запросами в клиент LLM.

[-chain] [-parallel] - Наследие от первой версии FzGen, не поддержаны все изменения, нет полного тестирования.

Использование

fzgen {flags} {name_of_package}
Примеры
fzgen io 
package main

// Edit if desired. Code generated by "fzgen io".

import (
	"fmt"
	io "io"
	"reflect"
	"testing"

	"github.com/BelehovEgor/fzgen/fuzzer"
)

func Fuzz_N1_LimitedReader_Read(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		var l *io.LimitedReader
		var p []byte
		fz := fuzzer.NewFuzzerV2(data, FabricFuncsForCustomTypes, t, fuzzer.Constructors)
		err := fz.Fill2(&l, &p)
		if err != nil || l == nil {
			return
		}

		// Put here your precondition of func arguments...

		l.Read(p)

		// Put here your postcondition of func results...
	})
}
//...

func fabric_constructor_wrapper_TeeReader_0(
	r io.Reader,
	w io.Writer,
) (result io.Reader, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("runtime panic: %v", r)
		}
	}()

	res := io.TeeReader(
		r,
		w,
	)
	return res, err
}

func fabric_constructor_wrapper_NopCloser_0(
	r io.Reader,
) (result io.ReadCloser, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("runtime panic: %v", r)
		}
	}()

	res := io.NopCloser(
		r,
	)
	return res, err
}

func fabric_constructor_wrapper_NewSectionReader_0(
	r io.ReaderAt,
	off int64,
	n int64,
) (result io.SectionReader, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("runtime panic: %v", r)
		}
	}()

	res := io.NewSectionReader(
		r,
		off,
		n,
	)
	return *res, err
}

func fabric_constructor_wrapper_MultiWriter_0(
	writers []io.Writer,
) (result io.Writer, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("runtime panic: %v", r)
		}
	}()

	res := io.MultiWriter(
		writers...,
	)
	return res, err
}

var FabricFuncsForCustomTypes map[string][]reflect.Value

func TestMain(m *testing.M) {
	FabricFuncsForCustomTypes = make(map[string][]reflect.Value)
	FabricFuncsForCustomTypes["io.Writer"] = append(FabricFuncsForCustomTypes["io.Writer"], reflect.ValueOf(fabric_constructor_wrapper_MultiWriter_0))
	FabricFuncsForCustomTypes["io.Reader"] = append(FabricFuncsForCustomTypes["io.Reader"], reflect.ValueOf(fabric_constructor_wrapper_TeeReader_0))
	FabricFuncsForCustomTypes["io.WriterAt"] = append(FabricFuncsForCustomTypes["io.WriterAt"], reflect.ValueOf(fabric_interface_io_WriterAt_OffsetWriter))
	FabricFuncsForCustomTypes["io.ReaderAt"] = append(FabricFuncsForCustomTypes["io.ReaderAt"], reflect.ValueOf(fabric_interface_io_ReaderAt_SectionReader))
	FabricFuncsForCustomTypes["io.ReadCloser"] = append(FabricFuncsForCustomTypes["io.ReadCloser"], reflect.ValueOf(fabric_constructor_wrapper_NopCloser_0))
	FabricFuncsForCustomTypes["io.SectionReader"] = append(FabricFuncsForCustomTypes["io.SectionReader"], reflect.ValueOf(fabric_constructor_wrapper_NewSectionReader_0))
	FabricFuncsForCustomTypes["interface {}"] = append(FabricFuncsForCustomTypes["interface {}"], reflect.ValueOf(fabric_interface_empty_PipeReader))
	FabricFuncsForCustomTypes["interface {}"] = append(FabricFuncsForCustomTypes["interface {}"], reflect.ValueOf(fabric_interface_empty_OffsetWriter))
	FabricFuncsForCustomTypes["interface {}"] = append(FabricFuncsForCustomTypes["interface {}"], reflect.ValueOf(fabric_interface_empty_LimitedReader))
	FabricFuncsForCustomTypes["interface {}"] = append(FabricFuncsForCustomTypes["interface {}"], reflect.ValueOf(fabric_interface_empty_string))
	FabricFuncsForCustomTypes["interface {}"] = append(FabricFuncsForCustomTypes["interface {}"], reflect.ValueOf(fabric_interface_empty_SectionReader))
	FabricFuncsForCustomTypes["interface {}"] = append(FabricFuncsForCustomTypes["interface {}"], reflect.ValueOf(fabric_interface_empty_PipeWriter))
	m.Run()
}
fzgen -unexported io 
func Fuzz_N28_pipe_writeCloseError(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		var p *io.pipe
		fz := fuzzer.NewFuzzerV2(data, FabricFuncsForCustomTypes, t, fuzzer.Constructors)
		err := fz.Fill2(&p)
		if err != nil || p == nil {
			return
		}

		// Put here your precondition of func arguments...

		p.writeCloseError()

		// Put here your postcondition of func results...
	})
}
fzgen -mocks -mocksPackagePrefix=example -mocksDepth=3 net/http
func fabric_mock_interface_21_File(
	t *testing.T,
	error_ error,
	n int,
	err error,
	fileinfo_ []fs.FileInfo,
	error__1 error,
	int64_ int64,
	error__2 error,
	fileinfo__1 fs.FileInfo,
	error__3 error,
) http.File {
	genMock := mocks_2.NewMockFile(t)
	genMock.
		On("Close").
		Return(func() error {
			return error_
		}).
		Maybe()
	genMock.
		On("Read", mock.AnythingOfType("[]byte")).
		Return(func(p []byte) (n int, err error) {
			return n, err
		}).
		Maybe()
	genMock.
		On("Readdir", mock.AnythingOfType("int")).
		Return(func(count int) ([]fs.FileInfo, error) {
			return fileinfo_, error__1
		}).
		Maybe()
	genMock.
		On("Seek", mock.AnythingOfType("int64"), mock.AnythingOfType("int")).
		Return(func(offset int64, whence int) (int64, error) {
			return int64_, error__2
		}).
		Maybe()
	genMock.
		On("Stat").
		Return(func() (fs.FileInfo, error) {
			return fileinfo__1, error__3
		}).
		Maybe()
	return genMock
}
fzgen -structFillMode=ConstructorsAndRandom net/http
func Fuzz_N77_Get(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		var url_0 string
		fz := fuzzer.NewFuzzerV2(data, FabricFuncsForCustomTypes, t, fuzzer.ConstructorsAndRandom)
		err := fz.Fill2(&url_0)
		if err != nil {
			return
		}

		// Put here your precondition of func arguments...

		http.Get(url_0)

		// Put here your postcondition of func results...
	})
}
fzgen -fillUnexported regexp
func Fuzz_N39_Regexp_UnmarshalText(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		var re *regexp.Regexp
		var text []byte
		fz := fuzzer.NewFuzzerV2(data, FabricFuncsForCustomTypes, t, fuzzer.Constructors, fuzzer.FillUnexported)
		err := fz.Fill2(&re, &text)
		if err != nil || re == nil {
			return
		}

		// Put here your precondition of func arguments...

		re.UnmarshalText(text)

		// Put here your postcondition of func results...
	})
}
export openrouter_api_key=key
export timeout=10
fzgen -llm=openrouter sort
func Fuzz_N24_SearchFloat64s(f *testing.F) {
	f.Fuzz(func(t *testing.T, data []byte) {
		var a []float64
		var x float64
		fz := fuzzer.NewFuzzerV2(data, FabricFuncsForCustomTypes, t, fuzzer.Constructors)
		err := fz.Fill2(&a, &x)
		if err != nil {
			return
		}

		// Check if the slice is sorted in ascending order
		for i := 1; i < len(a); i++ {
			if a[i] < a[i-1] {
				return
			}
		}

		sort.SearchFloat64s(a, x)

		// Check if the result index is valid
		result := sort.SearchFloat64s(a, x)
		if result < 0 || result > len(a) {
			t.Error("result index out of bounds")
		}

		// Check if the result index is correct
		if result < len(a) && a[result] < x {
			t.Error("result index is incorrect")
		}
		if result > 0 && a[result-1] >= x {
			t.Error("result index is incorrect")
		}
	})
}

Directories

Path Synopsis
cmd
fuzzcheck command
fzgen command
Command fzgen automatically generates fuzz functions.
Command fzgen automatically generates fuzz functions.
examples
inputs/arg-reuse
Package argexample shows an example that would take longer to to panic simply using dvyukov/go-fuzz or 'go test -fuzz=.', but which should panic in 20-30 sec or so via fz.Chain when fz.Chain is properly reusing input arg values from a step as candidate input values to another step (currently just a few seconds with GODEBUG=fuzzseed=1, vs.
Package argexample shows an example that would take longer to to panic simply using dvyukov/go-fuzz or 'go test -fuzz=.', but which should panic in 20-30 sec or so via fz.Chain when fz.Chain is properly reusing input arg values from a step as candidate input values to another step (currently just a few seconds with GODEBUG=fuzzseed=1, vs.
inputs/race
raceexample wraps sync.Map in a type-safe way, but sadly the implementation has a a possible data race in handling a counter on the objects stored in the sync.Map.
raceexample wraps sync.Map in a type-safe way, but sadly the implementation has a a possible data race in handling a counter on the objects stored in the sync.Map.
inputs/return-reuse
Package returnexample shows an example that would be quite challenging to panic simply using dvyukov/go-fuzz or 'go test -fuzz=.', but which should panic almost immediately via fz.Chain when fz.Chain is properly wiring the return values from a step as candidate input values to another step.
Package returnexample shows an example that would be quite challenging to panic simply using dvyukov/go-fuzz or 'go test -fuzz=.', but which should panic almost immediately via fz.Chain when fz.Chain is properly wiring the return values from a step as candidate input values to another step.
inputs/test-chain-uuid
Package uuid is a simplified example for testing, roughly modeled on github.com/google/uuid.UUID.
Package uuid is a simplified example for testing, roughly modeled on github.com/google/uuid.UUID.
Package fuzzer supports fuzzing rich signatures via the Fill method, as well as the ability to automatically chain Steps together under the control of the fuzzer using the Chain method.
Package fuzzer supports fuzzing rich signatures via the Fill method, as well as the ability to automatically chain Steps together under the control of the fuzzer using the Chain method.
internal/randparam
Package randparam allows a []byte to be used as a source of random parameter values.
Package randparam allows a []byte to be used as a source of random parameter values.
gen
Package gen automatically generates fuzz functions, and is the main entry point for the fzgen command.
Package gen automatically generates fuzz functions, and is the main entry point for the fzgen command.
llm

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL