# These steps validate we can fuzz outside of GOPATH
# with GO111MODULE auto, on, unset, and off.
 
# The foo module being fuzzed depends on a 'replace' 
# in its go.mod to find one of its dependencies,
# which is a way to check that module-mode is required to compile successfully.

# Enter a simple module with a fuzz function.
# This is outside of GOPATH.
cd foo

# Copy a pristine go.mod file.
cp go.mod_PRISTINE go.mod

# First, we test with GO111MODULE=auto, which is the default
# in Go 1.11-1.13. (In 1.14, the default will likely be GO111MODULE=on).
env GO111MODULE=auto

# Sanity check the module seems well formed.
exec go list -m all
stdout '^example.com/foo$'
exec go build

# Because we are outside GOPATH, the presence of the 'go.mod' here will
# enable module-module for cmd/go with GO111MODULE=auto.
# This is true in Go 1.11-1.13, and likely will be true in 1.14 as well.
# Ask go-fuzz-build to build, including specifying the fuzz function for mod.
exec go-fuzz-build -func=FuzzMod
exists foo-fuzz.zip

# Validate we can start fuzzing.
# Note that 'timeout(1)' will error here, so we preface the invocation with '!'.
# For travis on Windows, we install 'timeout(1)' as part of our travis setup steps.
# To test this locally on Windows, you might need to change 'timeout' to '\cygwin64\bin\timeout' or similar.
! exec timeout 5 go-fuzz -procs=1 -func=FuzzMod
stderr 'workers: \d+, corpus: '

# Clean up.
cp go.mod_PRISTINE go.mod
rm foo-fuzz.zip

# Second, we test with GO111MODULE=on, which will likely be the default in Go 1.14.
env GO111MODULE=on

# Sanity check we can still interact with the module.
exec go list -m all
stdout '^example.com/foo$'
exec go build

# Ask go-fuzz-build to build, including specifying the fuzz function for mod.
exec go-fuzz-build -func=FuzzMod
exists foo-fuzz.zip

# Validate we can start fuzzing.
! exec timeout 5 go-fuzz -procs=1 -func=FuzzMod
stderr 'workers: \d+, corpus: '

# Clean up.
cp go.mod_PRISTINE go.mod
rm foo-fuzz.zip

# Third, we test with GO111MODULE unset.
# The meaning of this will likely change in Go 1.14, but given we are 
# outside of GOPATH, in theory these steps will still work even in Go 1.14.
env GO111MODULE=

# Sanity check we can still interact with the module.
exec go list -m all
stdout '^example.com/foo$'
exec go build

# Ask go-fuzz-build to build, including specifying the fuzz function for mod.
exec go-fuzz-build -func=FuzzMod
exists foo-fuzz.zip

# Validate we can start fuzzing.
! exec timeout 5 go-fuzz -procs=1 -func=FuzzMod
stderr 'workers: \d+, corpus: '

# Clean up.
cp go.mod_PRISTINE go.mod
rm foo-fuzz.zip

# Fourth, we test with GO111MODULE=off.
# The meaning of this is unlikely to change in Go 1.14,
# altough in some (distant?) future, GO111MODULE=off might
# no longer be supported.
env GO111MODULE=off

# Confirm 'go list -m' and 'go build' fail.
! exec go list -m all
! exec go build

# Confirm go-fuzz-build fails.
! exec go-fuzz-build -func=FuzzMod
! exists foo-fuzz.zip

# Clean up (mainly in case we later add another test below).
cp go.mod_PRISTINE go.mod
rm foo-fuzz.zip

# Define two modules.
# example.com/foo has a fuzz function, and depends on example.com/bar.

-- foo/go.mod_PRISTINE --
module example.com/foo

require example.com/bar v0.0.0

replace example.com/bar => ../bar

-- foo/fuzz.go --
package foo

import "example.com/bar"

func FuzzMod(data []byte) int {
	bar.Bar()
	return 0
}

-- bar/go.mod --
module example.com/bar

-- bar/bar.go --
package bar

func Bar() string {
	return "hello from bar"
}

