diff --git a/.github/workflows/client.yml b/.github/workflows/client.yml index 79cf111..07f840b 100644 --- a/.github/workflows/client.yml +++ b/.github/workflows/client.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macOS-latest"] - go: ["1.17.x", "1.18.x", "1.19.x"] + go: ["1.18.x", "1.19.x"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 57a41ea..f7e2fee 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ site # Test binary, built with `go test -c` *.test +testdata # Output of the go coverage tool, specifically when used with LiteIDE *.out @@ -29,4 +30,4 @@ data/ # docker genesis documents testnet/conf/node*/config/genesis.json -plugin/ops/__pycache__ \ No newline at end of file +plugin/ops/__pycache__ diff --git a/client/README.md b/client/README.md index 8965bca..a6ef3a0 100644 --- a/client/README.md +++ b/client/README.md @@ -15,6 +15,8 @@ docker run --rm \ -w /client \ golang:buster \ /bin/bash -c "GORACE=history_size=7 go test -race" + ## or to run fuzzing use below command + # go test -fuzz ./... ``` The above can be de-constructed as follows: @@ -24,3 +26,18 @@ The above can be de-constructed as follows: - `-w /client`: Working directory for the docker image - `golang:buster`: The docker image to be used - `/bin/bash -c "GORACE=history_size=7 go test -race"`: The command to run inside the container + + +### Fuzzing test + +To run fuzzing test +``` +go test -fuzz= +``` + +example: `go test -fuzz=FuzzQueuePushSerial` + +- Tests + - FuzzQueue + - FuzzQueuePushSerial + - FuzzQueuePushParalell diff --git a/client/queue_test.go b/client/queue_test.go index e03aafb..d144796 100644 --- a/client/queue_test.go +++ b/client/queue_test.go @@ -1,9 +1,11 @@ package client import ( + "testing" + "sync" + "github.com/katzenpost/client/constants" "github.com/stretchr/testify/assert" - "testing" ) type foo struct { @@ -39,3 +41,66 @@ func TestQueue(t *testing.T) { _, err = q.Pop() assert.Error(err) } + +func FuzzQueue(f *testing.F) { + f.Fuzz(func(t *testing.T, _, s string) { + q := new(Queue) + t.Log("Pushing", s) + err := q.Push(foo{s}) + if err != nil { + t.Errorf("Push %v %v", s, err) + } + item, err := q.Pop() + if err != nil { + t.Errorf("Pop %v %v %v", s, item, err) + } + }) +} + +func FuzzQueuePushSerial(f *testing.F) { + f.Fuzz(func(t *testing.T, i int, s string) { + q := new(Queue) + if i > constants.MaxEgressQueueSize { + return + } + for j := 0; j < i; j++ { + t.Log("Pushing", s) + err := q.Push(foo{s}) + if err != nil { + t.Errorf("Push %v %v", s, err) + } + } + }) +} + +func FuzzQueuePushParalell(f *testing.F) { + f.Add(1, "abcde") + f.Add(1, "") + f.Add(1, string([]byte{0x00})) + f.Fuzz(func(t *testing.T, i int, s string) { + q := new(Queue) + if i > constants.MaxEgressQueueSize { + return + } + if i < 0 { + return + } + t.Logf("Pushing '%v' for %v times", s, i) + var wg sync.WaitGroup + for j := 0; j < i; j++ { + t.Log("Pushing", s) + wg.Add(1) + go func(wg *sync.WaitGroup, s string, q *Queue, t *testing.T) { + defer wg.Done() + err := q.Push(foo{s}) + if err != nil { + t.Errorf("Push %v %v", s, err) + } + }(&wg, s, q, t) + } + wg.Wait() + if q.len != i { + t.Errorf("Expected len: %v, actual %v", i, q.len) + } + }) +}