Skip to content

testing: cover profile indicates zero coverage of function under test #48178

Closed
@stevenjohnstone

Description

@stevenjohnstone

What version of Go are you using (go version)?

$ go version
go version devel go1.17-e5247f7886a Thu Sep 2 21:43:52 2021 +0000 linux/amd64

Does this issue reproduce with the latest release?

n/a

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/stevie/.cache/go-build"
GOENV="/home/stevie/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/stevie/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/stevie/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/stevie/sdk/gotip"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/stevie/sdk/gotip/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="devel go1.17-e5247f7886a Thu Sep 2 21:43:52 2021 +0000"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/stevie/code/coverbug/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1073398343=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I have two files

package coverbug

import "testing"

func Fuzz(f *testing.F) {
	f.Fuzz(func(t *testing.T, a byte) {
		if magic(a) {
			panic(a)
		}
	})
}
package coverbug

func magic(a byte) bool {
	return a == 127
}

I run the beta fuzzer with coverage enabled

$ gotip test -fuzz=Fuzz -coverprofile=cover.out
found a crash, minimizing...
coverage: 100.0% of statements
coverage: 100.0% of statements
coverage: 0.0% of statements
coverage: 100.0% of statements
coverage: 100.0% of statements
coverage: 100.0% of statements
coverage: 100.0% of statements
coverage: 100.0% of statements
fuzzing, elapsed: 0.0s, execs: 184 (6166/sec), workers: 8, interesting: 0
--- FAIL: Fuzz (0.03s)
        panic: %!s(uint8=127)
        goroutine 48 [running]:
        runtime/debug.Stack()
        	/home/stevie/sdk/gotip/src/runtime/debug/stack.go:24 +0x90
        testing.tRunner.func1.2({0x58ce60, 0x6e2db8})
        	/home/stevie/sdk/gotip/src/testing/testing.go:1281 +0x267
        testing.tRunner.func1()
        	/home/stevie/sdk/gotip/src/testing/testing.go:1288 +0x218
        panic({0x58ce60, 0x6e2db8})
        	/home/stevie/sdk/gotip/src/runtime/panic.go:1038 +0x215
        coverbug.Fuzz.func1(0x0, 0x7f)
        	/home/stevie/code/coverbug/fuzz_test.go:8 +0x8b
        reflect.Value.call({0x58e940, 0x5c7bf0, 0x13}, {0x5ba226, 0x4}, {0xc00007aba0, 0x2, 0x2})
        	/home/stevie/sdk/gotip/src/reflect/value.go:543 +0x814
        reflect.Value.Call({0x58e940, 0x5c7bf0, 0xc000077e10}, {0xc00007aba0, 0x2, 0x2})
        	/home/stevie/sdk/gotip/src/reflect/value.go:339 +0xc5
        testing.(*F).Fuzz.func1.1(0xc00006a1e0)
        	/home/stevie/sdk/gotip/src/testing/fuzz.go:389 +0x1c6
        testing.tRunner(0xc0002361a0, 0xc000074b00)
        	/home/stevie/sdk/gotip/src/testing/testing.go:1335 +0x102
        created by testing.(*F).Fuzz.func1
        	/home/stevie/sdk/gotip/src/testing/fuzz.go:378 +0x505
        
        --- FAIL: Fuzz (0.00s)
    
    Crash written to testdata/corpus/Fuzz/4498dff1b840228ff50fd74740fe7690b5abeb3c9389d686b18a4bd3144abbbb
    To re-run:
    go test coverbug -run=Fuzz/4498dff1b840228ff50fd74740fe7690b5abeb3c9389d686b18a4bd3144abbbb
FAIL
coverage: 0.0% of statements
exit status 1
FAIL	coverbug	0.033s
$ cat cover.out 
mode: set
coverbug/magic.go:3.25,5.2 1 0

Note that the cover.out indicates zero coverage of the function magic, which can't be correct as the fuzzer just visited it before the panic.

If I run the test again, with coverage going to cover2.out, the previous crasher is read from ./testdata and used immediately in the corpus based test stage and I see

$ diff cover.out cover2.out 
2c2
< coverbug/magic.go:3.25,5.2 1 0
---
> coverbug/magic.go:3.25,5.2 1 1

Summary: run the fuzzer once to find a crasher, you get no coverage. Start the fuzzer again, you get coverage for the run using the crasher.

What did you expect to see?

I expected to see correct coverage information.

What did you see instead?

I saw zero counts on all the provided coverage points.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.fuzzIssues related to native fuzzing supportrelease-blocker

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions