@@ -11,6 +11,7 @@ import (
1111 "os"
1212 "os/exec"
1313 "path/filepath"
14+ "regexp"
1415 "strings"
1516 "time"
1617
@@ -852,7 +853,19 @@ func (r *runner) runSingleTest(ctx context.Context, metadata types.ValidatorMeta
852853 cmd , cleanup := r .testCommandContext (ctx , r .goBinary , args ... )
853854 defer cleanup ()
854855
855- stdoutFile , err := os .CreateTemp ("" , "op-acceptor-stdout-*.log" )
856+ // Create stdout temp file under log dir when available, so that if the process
857+ // is killed mid-test the file remains in the run directory for investigation.
858+ // Completed tests have the file processed and then deleted in defer.
859+ // Include sanitized package name in the filename for identification.
860+ stdoutTempDir := ""
861+ if r .fileLogger != nil {
862+ if logDir , err := r .fileLogger .GetDirectoryForRunID (r .runID ); err == nil {
863+ stdoutTempDir = logDir
864+ }
865+ }
866+ pkgPrefix := sanitizeForFilename (metadata .Package , maxStdoutTempPrefixLen )
867+ stdoutPattern := "op-acceptor-stdout-" + pkgPrefix + "-*.log"
868+ stdoutFile , err := os .CreateTemp (stdoutTempDir , stdoutPattern )
856869 if err != nil {
857870 return nil , fmt .Errorf ("failed to create stdout temp file: %w" , err )
858871 }
@@ -1041,6 +1054,29 @@ func (r *runner) parseTestOutput(output io.Reader, metadata types.ValidatorMetad
10411054 return r .outputParser .Parse (output , metadata )
10421055}
10431056
1057+ // maxStdoutTempPrefixLen limits the package-based prefix in stdout temp filenames
1058+ // so the full path stays well under PATH_MAX (1024 on Unix/macOS).
1059+ const maxStdoutTempPrefixLen = 80
1060+
1061+ // invalidFilenameChars matches one or more characters not allowed in a filename component (Unix/macOS).
1062+ // Runs are replaced with a single '_' so e.g. "foo///bar" becomes "foo_bar".
1063+ var invalidFilenameChars = regexp .MustCompile (`[^a-zA-Z0-9_.\-]+` )
1064+
1065+ // sanitizeForFilename returns a string safe for use in a filename or path component:
1066+ // only [a-zA-Z0-9_.-] are kept, others replaced with '_', truncated to maxLen (keeping the end).
1067+ // Returns "pkg" if the result would be empty.
1068+ func sanitizeForFilename (s string , maxLen int ) string {
1069+ out := invalidFilenameChars .ReplaceAllString (s , "_" )
1070+ out = strings .Trim (out , "._-" )
1071+ if len (out ) > maxLen {
1072+ out = out [len (out )- maxLen :]
1073+ }
1074+ if out == "" {
1075+ return "pkg"
1076+ }
1077+ return out
1078+ }
1079+
10441080func buildStdoutSnippet (buf * tailBuffer ) string {
10451081 if buf == nil || buf .TotalBytes () == 0 {
10461082 return ""
0 commit comments