Skip to content

Commit

Permalink
fuzz: add more fuzz tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Jorropo committed Feb 5, 2024
1 parent 070a396 commit 234c3f6
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 27 deletions.
29 changes: 17 additions & 12 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"runtime/debug"
"testing"
)

// ErrNotSupported is the error returned when the muxer doesn't support
Expand Down Expand Up @@ -35,12 +36,14 @@ var ErrNoProtocols = errors.New("no protocols specified")
// on this ReadWriteCloser. It returns an error if, for example,
// the muxer does not know how to handle this protocol.
func SelectProtoOrFail[T StringLike](proto T, rwc io.ReadWriteCloser) (err error) {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic selecting protocol: %s", rerr)
}
}()
if !testing.Testing() {

Check failure on line 39 in client.go

View workflow job for this annotation

GitHub Actions / go-check / All

undefined: testing.Testing
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic selecting protocol: %s", rerr)
}

Check warning on line 44 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L40-L44

Added lines #L40 - L44 were not covered by tests
}()
}

errCh := make(chan error, 1)
go func() {
Expand Down Expand Up @@ -70,12 +73,14 @@ func SelectProtoOrFail[T StringLike](proto T, rwc io.ReadWriteCloser) (err error
// SelectOneOf will perform handshakes with the protocols on the given slice
// until it finds one which is supported by the muxer.
func SelectOneOf[T StringLike](protos []T, rwc io.ReadWriteCloser) (proto T, err error) {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic selecting one of protocols: %s", rerr)
}
}()
if !testing.Testing() {

Check failure on line 76 in client.go

View workflow job for this annotation

GitHub Actions / go-check / All

undefined: testing.Testing
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic selecting one of protocols: %s", rerr)
}

Check warning on line 81 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L77-L81

Added lines #L77 - L81 were not covered by tests
}()
}

if len(protos) == 0 {
return "", ErrNoProtocols
Expand Down
15 changes: 9 additions & 6 deletions multistream.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"runtime/debug"
"sync"
"testing"

"github.com/multiformats/go-varint"
)
Expand Down Expand Up @@ -192,12 +193,14 @@ func (msm *MultistreamMuxer[T]) findHandler(proto T) *Handler[T] {
// Negotiate performs protocol selection and returns the protocol name and
// the matching handler function for it (or an error).
func (msm *MultistreamMuxer[T]) Negotiate(rwc io.ReadWriteCloser) (proto T, handler HandlerFunc[T], err error) {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic in multistream negotiation: %s", rerr)
}
}()
if !testing.Testing() {

Check failure on line 196 in multistream.go

View workflow job for this annotation

GitHub Actions / go-check / All

undefined: testing.Testing (compile)
defer func() {
if rerr := recover(); rerr != nil {
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
err = fmt.Errorf("panic in multistream negotiation: %s", rerr)
}

Check warning on line 201 in multistream.go

View check run for this annotation

Codecov / codecov/patch

multistream.go#L197-L201

Added lines #L197 - L201 were not covered by tests
}()
}

// Send the multistream protocol ID
// Ignore the error here. We want the handshake to finish, even if the
Expand Down
66 changes: 57 additions & 9 deletions multistream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"net"
"slices"

Check failure on line 10 in multistream_test.go

View workflow job for this annotation

GitHub Actions / go-test / ubuntu (go this)

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.13/x64/src/slices)

Check failure on line 10 in multistream_test.go

View workflow job for this annotation

GitHub Actions / go-check / All

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.13/x64/src/slices)

Check failure on line 10 in multistream_test.go

View workflow job for this annotation

GitHub Actions / go-check / All

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.13/x64/src/slices) (compile)

Check failure on line 10 in multistream_test.go

View workflow job for this annotation

GitHub Actions / go-test / windows (go this)

package slices is not in GOROOT (C:\hostedtoolcache\windows\go\1.20.13\x64\src\slices)

Check failure on line 10 in multistream_test.go

View workflow job for this annotation

GitHub Actions / go-test / macos (go this)

package slices is not in GOROOT (/Users/runner/hostedtoolcache/go/1.20.12/x64/src/slices)
"sort"
"strings"
"testing"
Expand Down Expand Up @@ -802,7 +803,7 @@ func TestNegotiatePeerSendsAndCloses(t *testing.T) {
}

type rwc struct {
*strings.Reader
strings.Reader
}

func (*rwc) Write(b []byte) (int, error) {
Expand All @@ -813,21 +814,68 @@ func (*rwc) Close() error {
return nil
}

func FuzzMultistream(f *testing.F) {
f.Add("/multistream/1.0.0")
f.Add(ProtocolID)
func FuzzHandler(f *testing.F) {
f.Add("/noise", "/tls", "", "\x13/multistream/1.0.0\n\a/noise\n")

f.Fuzz(func(t *testing.T, b string) {
readStream := strings.NewReader(b)
input := &rwc{readStream}
f.Fuzz(func(t *testing.T, p1, p2, p3, b string) {
input := &rwc{*strings.NewReader(b)}

mux := NewMultistreamMuxer[string]()
mux.AddHandler("/a", nil)
mux.AddHandler("/b", nil)
h := func(protocol string, rwc io.ReadWriteCloser) error {
defer rwc.Close()
_, err := io.Copy(io.Discard, rwc)
return err
}
if p1 != "" {
mux.AddHandler(p1, h)
}
if p2 != "" {
mux.AddHandler(p2, h)
}
if p3 != "" {
mux.AddHandler(p3, h)
}
_ = mux.Handle(input)
})
}

func FuzzSelectOneOf(f *testing.F) {
f.Add("/noise", "/tls", "", "\x13/multistream/1.0.0\n\a/noise\n")

f.Fuzz(func(t *testing.T, p1, p2, p3, response string) {
protos := make([]string, 0, 3)
if p1 != "" {
protos = append(protos, p1)
}
if p2 != "" {
protos = append(protos, p2)
}
if p3 != "" {
protos = append(protos, p3)
}

r := &rwc{*strings.NewReader(response)}

p, err := SelectOneOf(protos, r)
if err != nil {
return
}
if !slices.Contains(protos, p) {
t.Fatal("matched proto which wasn't proposed")
}
})
}

func FuzzSelectOrFail(f *testing.F) {
f.Add("/noise", "\x13/multistream/1.0.0\n\a/noise\n")

f.Fuzz(func(t *testing.T, proto, response string) {
r := &rwc{*strings.NewReader(response)}

_ = SelectProtoOrFail(proto, r)
})
}

func TestComparableErrors(t *testing.T) {
var err1 error = ErrNotSupported[string]{[]string{"/a"}}
if !errors.Is(err1, ErrNotSupported[string]{}) {
Expand Down

0 comments on commit 234c3f6

Please sign in to comment.