feat(scanner): add fuzzing test
This commit is contained in:
90
server/scanner/scanner_fuzz_test.go
Normal file
90
server/scanner/scanner_fuzz_test.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
//go:build go1.18
|
||||||
|
// +build go1.18
|
||||||
|
|
||||||
|
package scanner_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||||
|
"github.com/matryer/is"
|
||||||
|
"go.senan.xyz/gonic/server/mockfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FuzzScanner(f *testing.F) {
|
||||||
|
checkDelta := func(is *is.I, m *mockfs.MockFS, expSeen, expNew int) {
|
||||||
|
is.Helper()
|
||||||
|
|
||||||
|
ctx := m.ScanAndClean()
|
||||||
|
is.Equal(ctx.SeenTracks(), expSeen)
|
||||||
|
is.Equal(ctx.SeenTracksNew(), expNew)
|
||||||
|
is.Equal(ctx.TracksMissing(), 0)
|
||||||
|
is.Equal(ctx.AlbumsMissing(), 0)
|
||||||
|
is.Equal(ctx.ArtistsMissing(), 0)
|
||||||
|
is.Equal(ctx.GenresMissing(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
is := is.NewRelaxed(t)
|
||||||
|
m := mockfs.New(t)
|
||||||
|
defer m.CleanUp()
|
||||||
|
|
||||||
|
const toAdd = 1000
|
||||||
|
for i := 0; i < toAdd; i++ {
|
||||||
|
path := fmt.Sprintf("artist-%d/album-%d/track-%d.flac", i/6, i/3, i)
|
||||||
|
m.AddTrack(path)
|
||||||
|
m.SetTags(path, func(tags *mockfs.Tags) { fuzzStruct(i, data, tags) })
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDelta(is, m, toAdd, toAdd) // we added all tracks, 0 delta
|
||||||
|
checkDelta(is, m, toAdd, 0) // we added 0 tracks, 0 delta
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func fuzzStruct(taken int, data []byte, dest interface{}) {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r := seedRand(data)
|
||||||
|
v := reflect.ValueOf(dest)
|
||||||
|
for i := 0; i < v.Elem().NumField(); i++ {
|
||||||
|
if r.Float64() < 0.1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
take := int(r.Float64() * 12)
|
||||||
|
b := make([]byte, take)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = data[(i+taken)%len(data)]
|
||||||
|
}
|
||||||
|
taken += take
|
||||||
|
|
||||||
|
switch f := v.Elem().Field(i); f.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
f.SetBool(b[0] < 128)
|
||||||
|
case reflect.String:
|
||||||
|
f.SetString(string(b))
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
f.SetInt(int64(b[0]))
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
f.SetUint(uint64(b[0]))
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
f.SetFloat(float64(b[0]))
|
||||||
|
case reflect.Struct:
|
||||||
|
fuzzStruct(taken, data, f.Addr().Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func seedRand(seed []byte) *rand.Rand {
|
||||||
|
b := make([]byte, 8)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = seed[i%len(seed)]
|
||||||
|
}
|
||||||
|
return rand.New(rand.NewSource(int64(binary.BigEndian.Uint64(b))))
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
[]byte("001")
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
[]byte("")
|
||||||
Reference in New Issue
Block a user