package blob import ( "fmt" "os" "path/filepath" "runtime" "strings" "testing" ) func isCaseSensitive(dir string) bool { defer func() { os.Remove(filepath.Join(dir, "_casecheck")) }() exists := func(file string) bool { _, err := os.Stat(file) return err == nil } file := filepath.Join(dir, "_casecheck") FILE := filepath.Join(dir, "_CASECHECK") if exists(file) || exists(FILE) { panic(fmt.Sprintf("_casecheck already exists in %q; remove and try again.", dir)) } err := os.WriteFile(file, nil, 0o666) if err != nil { panic(err) } return !exists(FILE) } func isCI() bool { return os.Getenv("CI") != "" } const volumeHint = ` Unable to locate case-insensitive TMPDIR on darwin. To run tests, create the case-insensitive volume /Volumes/data: $ sudo diskutil apfs addVolume disk1 APFSX data -mountpoint /Volumes/data or run with: CI=1 go test ./... ` // useCaseInsensitiveTempDir sets TMPDIR to a case-insensitive directory // can find one, otherwise it skips the test if the CI environment variable is // set, or GOOS is not darwin. func useCaseInsensitiveTempDir(t *testing.T) bool { if isCaseSensitive(os.TempDir()) { // Use the default temp dir if it is already case-sensitive. return true } if runtime.GOOS == "darwin" { // If darwin, check for the special case-sensitive volume and // use it if available. const volume = "/Volumes/data" _, err := os.Stat(volume) if err == nil { tmpdir := filepath.Join(volume, "tmp") os.MkdirAll(tmpdir, 0o700) t.Setenv("TMPDIR", tmpdir) return true } if isCI() { // Special case darwin in CI; it is not case-sensitive // by default, and we will be testing other platforms // that are case-sensitive, so we'll have the test // being skipped covered there. t.Skip("Skipping test in CI for darwin; TMPDIR is not case-insensitive.") } } if !isCI() { // Require devs to always tests with a case-insensitive TMPDIR. // TODO(bmizerany): Print platform-specific instructions or // link to docs on that topic. lines := strings.Split(volumeHint, "\n") for _, line := range lines { t.Log(line) } } return false }