From e485a0d5ffd5c94376b8b4a94a4cad3797c18009 Mon Sep 17 00:00:00 2001 From: Matt Farina Date: Fri, 7 Apr 2023 10:01:19 -0400 Subject: [PATCH] Migrating Fuzz testing to Go built-in testing This also sets up CI to regularly perform Fuzz testing. This first step with fuzzing migrated just the existing Fuzz tests to the new setup. In the future additional tests can be added. Signed-off-by: Matt Farina --- .github/workflows/fuzz.yaml | 20 ++++++++++++++++++++ Makefile | 17 +++++------------ constraints_test.go | 33 +++++++++++++++++++++++++++++++++ fuzz.go | 22 ---------------------- version_test.go | 24 ++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/fuzz.yaml delete mode 100644 fuzz.go diff --git a/.github/workflows/fuzz.yaml b/.github/workflows/fuzz.yaml new file mode 100644 index 0000000..05c2a05 --- /dev/null +++ b/.github/workflows/fuzz.yaml @@ -0,0 +1,20 @@ +name: Fuzz Testing +on: + # Perform Fuzz testing on PRs and on a daily basis. Daily will continue to + # look for problems. Doing this on PRs will look for issues introduced in + # a change. + pull_request: + schedule: + - cron: '33 23 * * *' # Run at 11:33 every day +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: "1.20" + - name: Checkout code + uses: actions/checkout@v3 + - name: Fuzz + run: make fuzz diff --git a/Makefile b/Makefile index eac1917..0e7b5c7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,5 @@ GOPATH=$(shell go env GOPATH) GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint -GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build -GOFUZZ = $(GOPATH)/bin/go-fuzz .PHONY: lint lint: $(GOLANGCI_LINT) @@ -19,19 +17,14 @@ test-cover: GO111MODULE=on go test -cover . .PHONY: fuzz -fuzz: $(GOFUZZBUILD) $(GOFUZZ) - @echo "==> Fuzz testing" - $(GOFUZZBUILD) - $(GOFUZZ) -workdir=_fuzz +fuzz: + @echo "==> Running Fuzz Tests" + go test -fuzz=FuzzNewVersion -fuzztime=15s . + go test -fuzz=FuzzStrictNewVersion -fuzztime=15s . + go test -fuzz=FuzzNewConstraint -fuzztime=15s . $(GOLANGCI_LINT): # Install golangci-lint. The configuration for it is in the .golangci.yml # file in the root of the repository echo ${GOPATH} curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1 - -$(GOFUZZBUILD): - cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build - -$(GOFUZZ): - cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep \ No newline at end of file diff --git a/constraints_test.go b/constraints_test.go index c725a95..c720797 100644 --- a/constraints_test.go +++ b/constraints_test.go @@ -776,3 +776,36 @@ func TestTextUnmarshalConstraints(t *testing.T) { } } } + +func FuzzNewConstraint(f *testing.F) { + testcases := []string{ + "v1.2.3", + " ", + "......", + "1", + "1.2.3-beta.1", + "1.2.3+foo", + "2.3.4-alpha.1+bar", + "lorem ipsum", + "*", + "!=1.2.3", + "^4.5", + "1.0.0 - 2", + "1.2.3.4.5.6", + ">= 1", + "~9.8.7", + "<= 12.13.14", + "987654321.123456789.654123789", + "1.x", + "2.3.x", + "9.2-beta.0", + } + + for _, tc := range testcases { + f.Add(tc) + } + + f.Fuzz(func(t *testing.T, a string) { + _, _ = NewConstraint(a) + }) +} diff --git a/fuzz.go b/fuzz.go deleted file mode 100644 index a242ad7..0000000 --- a/fuzz.go +++ /dev/null @@ -1,22 +0,0 @@ -// +build gofuzz - -package semver - -func Fuzz(data []byte) int { - d := string(data) - - // Test NewVersion - _, _ = NewVersion(d) - - // Test StrictNewVersion - _, _ = StrictNewVersion(d) - - // Test NewConstraint - _, _ = NewConstraint(d) - - // The return value should be 0 normally, 1 if the priority in future tests - // should be increased, and -1 if future tests should skip passing in that - // data. We do not have a reason to change priority so 0 is always returned. - // There are example tests that do this. - return 0 -} diff --git a/version_test.go b/version_test.go index 767dc29..16156dd 100644 --- a/version_test.go +++ b/version_test.go @@ -681,3 +681,27 @@ func TestValidateMetadata(t *testing.T) { } } } + +func FuzzNewVersion(f *testing.F) { + testcases := []string{"v1.2.3", " ", "......", "1", "1.2.3-beta.1", "1.2.3+foo", "2.3.4-alpha.1+bar", "lorem ipsum"} + + for _, tc := range testcases { + f.Add(tc) + } + + f.Fuzz(func(t *testing.T, a string) { + _, _ = NewVersion(a) + }) +} + +func FuzzStrictNewVersion(f *testing.F) { + testcases := []string{"v1.2.3", " ", "......", "1", "1.2.3-beta.1", "1.2.3+foo", "2.3.4-alpha.1+bar", "lorem ipsum"} + + for _, tc := range testcases { + f.Add(tc) + } + + f.Fuzz(func(t *testing.T, a string) { + _, _ = StrictNewVersion(a) + }) +}