Skip to content

Commit

Permalink
Remove fuzzing from sjson (#4520)
Browse files Browse the repository at this point in the history
  • Loading branch information
chilagrow authored Aug 8, 2024
1 parent 4bf4a7f commit 6fe9484
Show file tree
Hide file tree
Showing 20 changed files with 0 additions and 650 deletions.
136 changes: 0 additions & 136 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -274,139 +274,3 @@ jobs:
uses: FerretDB/github-actions/linters@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

fuzz-short:
name: Fuzz short
runs-on: ubuntu-22.04
timeout-minutes: 15

# Do not run this job in parallel for any PR change or branch push.
concurrency:
group: ${{ github.workflow }}-fuzz-short-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')

steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
with:
path: source
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website

- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
cache-key: fuzz

- name: Install Task
run: go generate -x
working-directory: source/tools

# TODO https://github.com/FerretDB/github-actions/issues/211

# Use deploy key instead of Personal Access Token (PAT) to limit access to one repository.
# If secrets are not available (for example, for a pull request from a fork), GITHUB_TOKEN PAT is used automatically.
- name: Checkout collected fuzz corpus
uses: actions/checkout@v4
with:
repository: FerretDB/fuzz-corpus
ssh-key: ${{ secrets.FUZZ_CORPUS_DEPLOY_KEY }}
path: fuzz-corpus
fetch-depth: 0 # for commit and push to work
lfs: false # LFS is used only by website

- name: Setup corpus
run: bin/task fuzz-corpus
working-directory: source

# precompile tests with unset GOMAXPROCS
- name: Init fuzzers
run: bin/task fuzz-init
working-directory: source

# TODO https://github.com/FerretDB/FerretDB/issues/238
# TODO https://github.com/FerretDB/FerretDB/issues/344
- name: Fuzz
run: bin/task fuzz FUZZ_TIME=1m
working-directory: source
env:
GOMAXPROCS: 1 # otherwise, oom-killer kills fuzzer too often

- name: Collect corpus
if: always()
run: bin/task fuzz-corpus
working-directory: source

# `secrets` are not supported in `if`, so we have to do this trick with environment variable:
# https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
# https://github.com/actions/runner/issues/520

- name: Push corpus if possible
if: always() && env.KEY != ''
env:
KEY: ${{ secrets.FUZZ_CORPUS_DEPLOY_KEY }}
run: |
set -x
git config user.name ferretdb-bot
git config user.email ferretdb-bot@ferretdb.io
git add --all .
git diff-index -p HEAD
git diff-index --quiet HEAD || git commit --message 'Update corpus'
git fetch
git rebase origin/main
git push
working-directory: fuzz-corpus

- name: Compress corpus before upload
if: failure() || env.KEY == ''
env:
KEY: ${{ secrets.FUZZ_CORPUS_DEPLOY_KEY }}
run: zip -r -q -9 fuzz-corpus.zip fuzz-corpus

- name: Upload corpus on failure or if push is not possible
if: failure() || env.KEY == ''
env:
KEY: ${{ secrets.FUZZ_CORPUS_DEPLOY_KEY }}
uses: actions/upload-artifact@v4
with:
name: fuzz-corpus
path: fuzz-corpus.zip
retention-days: 1
if-no-files-found: error

- name: Collect Linux logs
if: failure()
run: |
mkdir -p /tmp/logs
ls -al /var/log/
sudo cp /var/log/syslog /tmp/logs/
sudo free > /tmp/logs/free.txt
sudo chmod 0666 /tmp/logs/*
working-directory: source

- name: Compress Linux logs before upload
if: failure()
run: zip -r -q -9 linux-logs.zip /tmp/logs

- name: Upload Linux logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: linux-logs
path: linux-logs.zip
retention-days: 1
if-no-files-found: error

# we don't want them on CI
- name: Clean test and fuzz caches
if: always()
run: go clean -testcache -fuzzcache

- name: Check dirty
run: |
git status
git diff --exit-code
working-directory: source
26 changes: 0 additions & 26 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ vars:
TEST_RUN: ""
TEST_TIMEOUT: 35m
BENCH_TIME: 5s
FUZZ_TIME: 15s
FUZZ_CORPUS: ../fuzz-corpus
TESTJS_PORT: 27017
RACE_FLAG: -race={{and (ne OS "windows") (ne ARCH "arm") (ne ARCH "riscv64")}}
BUILD_TAGS: ferretdb_debug,ferretdb_hana
Expand Down Expand Up @@ -327,30 +325,6 @@ tasks:
- go test -count=10 -bench=BenchmarkDocument -benchtime={{.BENCH_TIME}} ./internal/bson/ | tee -a new.txt
- bin/benchstat{{exeExt}} old.txt new.txt

# That's not quite correct: https://github.com/golang/go/issues/15513
# But good enough for us.
fuzz-init:
deps: [gen-version]
cmds:
- go test -count=0 ./...

fuzz:
desc: "Fuzz for about 1 minute (with default FUZZ_TIME)"
cmds:
- go test -list='Fuzz.*' ./...
- go test -run=XXX -fuzz=FuzzDocument -fuzztime={{.FUZZ_TIME}} ./internal/bson/
- go test -run=XXX -fuzz=FuzzMsg -fuzztime={{.FUZZ_TIME}} ./internal/wire/
- go test -run=XXX -fuzz=FuzzQuery -fuzztime={{.FUZZ_TIME}} ./internal/wire/
- go test -run=XXX -fuzz=FuzzReply -fuzztime={{.FUZZ_TIME}} ./internal/wire/

fuzz-corpus:
desc: "Sync seed and generated fuzz corpora with FUZZ_CORPUS"
deps: [gen-version]
cmds:
- bin/envtool{{exeExt}} fuzz corpus generated {{.FUZZ_CORPUS}}
- bin/envtool{{exeExt}} fuzz corpus seed {{.FUZZ_CORPUS}}
- bin/envtool{{exeExt}} fuzz corpus {{.FUZZ_CORPUS}} generated

run:
desc: "Run FerretDB with `postgresql` backend"
deps: [build-host]
Expand Down
88 changes: 0 additions & 88 deletions internal/bson/bson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,91 +807,3 @@ func BenchmarkDocument(b *testing.B) {
})
}
}

// testRawDocument tests a single RawDocument (that might or might not be valid).
// It is adapted from tests above.
func testRawDocument(t *testing.T, rawDoc bson.RawDocument) {
t.Helper()

t.Run("bson", func(t *testing.T) {
t.Run("FindRaw", func(t *testing.T) {
ls := rawDoc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")

assert.NotEmpty(t, bson.LogMessage(rawDoc))
assert.NotEmpty(t, bson.LogMessageBlock(rawDoc))
assert.NotEmpty(t, bson.LogMessageFlow(rawDoc))

_, _ = bson.FindRaw(rawDoc)
})

t.Run("DecodeEncode", func(t *testing.T) {
doc, err := rawDoc.Decode()
if err != nil {
_, err = rawDoc.DecodeDeep()
assert.Error(t, err) // it might be different

return
}

ls := doc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")

assert.NotEmpty(t, bson.LogMessage(doc))
assert.NotEmpty(t, bson.LogMessageBlock(doc))
assert.NotEmpty(t, bson.LogMessageFlow(doc))

_, _ = doc.Convert()

raw, err := doc.Encode()
if err == nil {
assert.Equal(t, rawDoc, raw)
}
})

t.Run("DecodeDeepEncode", func(t *testing.T) {
doc, err := rawDoc.DecodeDeep()
if err != nil {
return
}

ls := doc.LogValue().Resolve().String()
assert.NotContains(t, ls, "panicked")
assert.NotContains(t, ls, "called too many times")

assert.NotEmpty(t, bson.LogMessage(doc))
assert.NotEmpty(t, bson.LogMessageBlock(doc))
assert.NotEmpty(t, bson.LogMessageFlow(doc))

_, err = doc.Convert()
require.NoError(t, err)

raw, err := doc.Encode()
require.NoError(t, err)
assert.Equal(t, rawDoc, raw)
})
})
}

func FuzzDocument(f *testing.F) {
for _, tc := range normalTestCases {
f.Add([]byte(tc.raw))
}

for _, tc := range decodeTestCases {
f.Add([]byte(tc.raw))
}

f.Fuzz(func(t *testing.T, b []byte) {
t.Parallel()

testRawDocument(t, bson.RawDocument(b))

l, err := bson.FindRaw(b)
if err == nil {
testRawDocument(t, bson.RawDocument(b[:l]))
}
})
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,6 @@ func TestArray(t *testing.T) {
testJSON(t, arrayTestCases, func() sjsontype { return new(arrayType) })
}

func FuzzArrayWithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, arrayTestCases, func() sjsontype { return new(arrayType) })
}

func FuzzArrayWithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, arrayTestCases, func() sjsontype { return new(arrayType) })
}

func BenchmarkArray(b *testing.B) {
benchmark(b, arrayTestCases, func() sjsontype { return new(arrayType) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ func TestBinary(t *testing.T) {
testJSON(t, binaryTestCases, func() sjsontype { return new(binaryType) })
}

func FuzzBinaryWithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, binaryTestCases, func() sjsontype { return new(binaryType) })
}

func FuzzBinaryWithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, binaryTestCases, func() sjsontype { return new(binaryType) })
}

func BenchmarkBinary(b *testing.B) {
benchmark(b, binaryTestCases, func() sjsontype { return new(binaryType) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/bool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ func TestBool(t *testing.T) {
testJSON(t, boolTestCases, func() sjsontype { return new(boolType) })
}

func FuzzBoolWithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, boolTestCases, func() sjsontype { return new(boolType) })
}

func FuzzBoolWithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, boolTestCases, func() sjsontype { return new(boolType) })
}

func BenchmarkBool(b *testing.B) {
benchmark(b, boolTestCases, func() sjsontype { return new(boolType) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/datetime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ func TestDateTime(t *testing.T) {
testJSON(t, dateTimeTestCases, func() sjsontype { return new(dateTimeType) })
}

func FuzzDateTimeWithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, dateTimeTestCases, func() sjsontype { return new(dateTimeType) })
}

func FuzzDateTimeWithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, dateTimeTestCases, func() sjsontype { return new(dateTimeType) })
}

func BenchmarkDateTime(b *testing.B) {
benchmark(b, dateTimeTestCases, func() sjsontype { return new(dateTimeType) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,14 +464,6 @@ func TestDocument(t *testing.T) {
testJSON(t, documentTestCases, func() sjsontype { return new(documentType) })
}

func FuzzDocumentWithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, documentTestCases, func() sjsontype { return new(documentType) })
}

func FuzzDocumentWithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, documentTestCases, func() sjsontype { return new(documentType) })
}

func BenchmarkDocument(b *testing.B) {
benchmark(b, documentTestCases, func() sjsontype { return new(documentType) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/double_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ func TestDouble(t *testing.T) {
testJSON(t, doubleTestCases, func() sjsontype { return new(doubleType) })
}

func FuzzDoubleWithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, doubleTestCases, func() sjsontype { return new(doubleType) })
}

func FuzzDoubleWithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, doubleTestCases, func() sjsontype { return new(doubleType) })
}

func BenchmarkDouble(b *testing.B) {
benchmark(b, doubleTestCases, func() sjsontype { return new(doubleType) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/int32_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ func TestInt32(t *testing.T) {
testJSON(t, int32TestCases, func() sjsontype { return new(int32Type) })
}

func FuzzInt32WithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, int32TestCases, func() sjsontype { return new(int32Type) })
}

func FuzzInt32WithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, int32TestCases, func() sjsontype { return new(int32Type) })
}

func BenchmarkInt32(b *testing.B) {
benchmark(b, int32TestCases, func() sjsontype { return new(int32Type) })
}
8 changes: 0 additions & 8 deletions internal/handler/sjson/int64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ func TestInt64(t *testing.T) {
testJSON(t, int64TestCases, func() sjsontype { return new(int64Type) })
}

func FuzzInt64WithFixedSchemas(f *testing.F) {
fuzzJSONWithFixedSchemas(f, int64TestCases, func() sjsontype { return new(int64Type) })
}

func FuzzInt64WithFixedDocuments(f *testing.F) {
fuzzJSONWithFixedDocuments(f, int64TestCases, func() sjsontype { return new(int64Type) })
}

func BenchmarkInt64(b *testing.B) {
benchmark(b, int64TestCases, func() sjsontype { return new(int64Type) })
}
Loading

0 comments on commit 6fe9484

Please sign in to comment.