aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/testdata/script/test_fuzz_io_error.txt
blob: 4c7ab4c152395c50549b3f596509f348a8449845 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Test that when the coordinator experiences an I/O error communicating
# with a worker, the coordinator stops the worker and reports the error.
# The coordinator should not record a crasher.
#
# We simulate an I/O error in the test by writing garbage to fuzz_out.
# This is unlikely, but possible. It's difficult to simulate interruptions
# due to ^C and EOF errors which are more common. We don't report those.
[short] skip
[!darwin] [!linux] [!windows] skip

# If the I/O error occurs before F.Fuzz is called, the coordinator should
# stop the worker and say that.
! go test -fuzz=FuzzClosePipeBefore -parallel=1
stdout '\s*fuzzing process terminated without fuzzing:'
! stdout 'communicating with fuzzing process'
! exists testdata

# If the I/O error occurs after F.Fuzz is called (unlikely), just exit.
# It's hard to distinguish this case from the worker being interrupted by ^C
# or exiting with status 0 (which it should do when interrupted by ^C).
! go test -fuzz=FuzzClosePipeAfter -parallel=1
stdout '^\s*communicating with fuzzing process: invalid character ''!'' looking for beginning of value$'
! exists testdata

-- go.mod --
module test

go 1.17
-- io_error_test.go --
package io_error

import (
	"flag"
	"testing"
	"time"
)

func isWorker() bool {
	f := flag.Lookup("test.fuzzworker")
	if f == nil {
		return false
	}
	get, ok := f.Value.(flag.Getter)
	if !ok {
		return false
	}
	return get.Get() == interface{}(true)
}

func FuzzClosePipeBefore(f *testing.F) {
	if isWorker() {
		sendGarbageToCoordinator(f)
		time.Sleep(3600 * time.Second) // pause until coordinator terminates the process
	}
	f.Fuzz(func(*testing.T, []byte) {})
}

func FuzzClosePipeAfter(f *testing.F) {
	f.Fuzz(func(t *testing.T, _ []byte) {
		if isWorker() {
			sendGarbageToCoordinator(t)
			time.Sleep(3600 * time.Second) // pause until coordinator terminates the process
		}
	})
}
-- io_error_windows_test.go --
package io_error

import (
	"fmt"
	"os"
	"testing"
)

func sendGarbageToCoordinator(tb testing.TB) {
	v := os.Getenv("GO_TEST_FUZZ_WORKER_HANDLES")
	var fuzzInFD, fuzzOutFD uintptr
	if _, err := fmt.Sscanf(v, "%x,%x", &fuzzInFD, &fuzzOutFD); err != nil {
		tb.Fatalf("parsing GO_TEST_FUZZ_WORKER_HANDLES: %v", err)
	}
	f := os.NewFile(fuzzOutFD, "fuzz_out")
	if _, err := f.Write([]byte("!!")); err != nil {
		tb.Fatalf("writing fuzz_out: %v", err)
	}
}
-- io_error_notwindows_test.go --
// +build !windows

package io_error

import (
	"os"
	"testing"
)

func sendGarbageToCoordinator(tb testing.TB) {
	f := os.NewFile(4, "fuzz_out")
	if _, err := f.Write([]byte("!!")); err != nil {
		tb.Fatalf("writing fuzz_out: %v", err)
	}
}