# Regression test for https://go.dev/issue/64589:
# This test is very similar to build_cc_cache_issue64423. Issue #64423
# was that we weren't properly parsing the versions output by the compiler.
# That test checked that we could parse the version and incorporate the
# version into the hash for the action id. This issue #64589 is that
# we treat all errors getting the version of the compiler the same, so
# we'd get the same action id for a missing compiler vs one whose
# version is unparseable. So the test now first does a run with a compiler
# that produces unparseable version output, and then runs it again with a missing
# compiler and ensures the command doesn't return the cached output for the
# first run when running the second run.

[!cgo] skip
[short] skip 'builds and links a fake clang binary'
[!cc:clang] skip 'test is specific to clang version parsing'

# Save the location of the real clang command for our fake one to use.
go run ./which clang
cp stdout $WORK/.realclang

# Build a fake clang and ensure that it is the one in $PATH.
mkdir $WORK/bin
go build -o $WORK/bin/clang$GOEXE ./fakeclang
[!GOOS:plan9] env PATH=$WORK${/}bin
[GOOS:plan9] env path=$WORK${/}bin

# Force CGO_ENABLED=1 so that the following commands should error
# out if the fake clang doesn't work.
env CGO_ENABLED=1

# The bug in https://go.dev/issue/64589 resulted in cache keys that
# didn't contain any information about the error getting the compiler version.
# Since the bug was in cache key computation, isolate the cache:
# if we change the way caching works, we want the test to fail
# instead of accidentally reusing the cached information from a
# previous test run.
env GOCACHE=$WORK${/}.cache
mkdir $GOCACHE

go build -x runtime/cgo

	# Tell our fake clang to stop working.
	# Previously, 'go build -x runtime/cgo' would continue to
	# succeed because both the broken clang and the non-broken one
	# resulted in a cache key with no clang version information.
env GO_BREAK_CLANG=1
! go build -x runtime/cgo
stderr '# runtime/cgo\nGO_BREAK_CLANG is set'

-- go.mod --
module example/issue64589
go 1.20
-- which/main.go --
package main

import (
	"os"
	"os/exec"
)

func main() {
	path, err := exec.LookPath(os.Args[1])
	if err != nil {
		panic(err)
	}
	os.Stdout.WriteString(path)
}
-- fakeclang/main.go --
package main

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"slices"
)

func main() {
	if os.Getenv("GO_BREAK_CLANG") != "" {
		os.Stderr.WriteString("GO_BREAK_CLANG is set\n")
		os.Exit(1)
	}

	b, err := os.ReadFile(filepath.Join(os.Getenv("WORK"), ".realclang"))
	if err != nil {
		log.Fatal(err)
	}
	if slices.Contains(os.Args, "-###") { // We are being run by gccToolID to determine the tool id used in the action id.
		return // The important thing is that we don't print the string "version"!
	}
	clang := string(bytes.TrimSpace(b))
	cmd := exec.Command(clang, os.Args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
}
