🔍 feat(bdd): add state tracer for debugging test execution and state pollution
- Add STATE_TRACER_README.md documenting purpose, usage, limitations, and future enhancements - Add state_tracer.go with per-process file-based tracing to $TMPDIR - Trace scenario start/end, database cleanup, JWT secret operations - Integrate tracing into suite.go BeforeScenario/AfterScenario hooks - Document findings: sequential execution per feature, shared database across processes - Identify root causes: in-memory JWT secrets not isolated by schema, config reload timing Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
86
pkg/bdd/testserver/state_tracer.go
Normal file
86
pkg/bdd/testserver/state_tracer.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package testserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TraceStateScenarioStart logs the start of a scenario
|
||||
func TraceStateScenarioStart(feature, scenario string) {
|
||||
writeTraceLine(feature, scenario, "SCENARIO_START", "")
|
||||
}
|
||||
|
||||
// TraceStateScenarioEnd logs the end of a scenario
|
||||
func TraceStateScenarioEnd(feature, scenario string, err error) {
|
||||
status := "PASSED"
|
||||
if err != nil {
|
||||
status = fmt.Sprintf("FAILED: %v", err)
|
||||
}
|
||||
writeTraceLine(feature, scenario, "SCENARIO_END", status)
|
||||
}
|
||||
|
||||
// TraceStateDBCleanup logs a database cleanup operation
|
||||
func TraceStateDBCleanup(feature, scenario, table string) {
|
||||
writeTraceLine(feature, scenario, "DB_CLEANUP", table)
|
||||
}
|
||||
|
||||
// TraceStateJWTSecretOperation logs a JWT secret operation
|
||||
func TraceStateJWTSecretOperation(feature, scenario, operation, details string) {
|
||||
writeTraceLine(feature, scenario, "JWT_"+operation, details)
|
||||
}
|
||||
|
||||
// TraceStateSchemaIsolation logs a schema isolation operation
|
||||
func TraceStateSchemaIsolation(feature, scenario, operation, details string) {
|
||||
writeTraceLine(feature, scenario, "SCHEMA_"+operation, details)
|
||||
}
|
||||
|
||||
// TraceStateTransaction logs a transaction boundary
|
||||
func TraceStateTransaction(feature, scenario, action, details string) {
|
||||
writeTraceLine(feature, scenario, "TX_"+action, details)
|
||||
}
|
||||
|
||||
// TraceStateDBRead logs a database read operation
|
||||
func TraceStateDBRead(feature, scenario, table, details string) {
|
||||
writeTraceLine(feature, scenario, "DB_SELECT", fmt.Sprintf("table=%s %s", table, details))
|
||||
}
|
||||
|
||||
// StateTracingEnabled returns true if BDD_TRACE_STATE environment variable is set to "1"
|
||||
func StateTracingEnabled() bool {
|
||||
return os.Getenv("BDD_TRACE_STATE") == "1"
|
||||
}
|
||||
|
||||
// writeTraceLine writes a trace line to the state trace file in $TMPDIR
|
||||
func writeTraceLine(feature, scenario, action, details string) {
|
||||
if !StateTracingEnabled() {
|
||||
return
|
||||
}
|
||||
tmpDir := os.Getenv("TMPDIR")
|
||||
if tmpDir == "" {
|
||||
tmpDir = "/tmp"
|
||||
}
|
||||
timestamp := time.Now().Format("20060102-150405")
|
||||
pid := os.Getpid()
|
||||
filename := fmt.Sprintf("bdd-state-trace-%s-%d.log", timestamp, pid)
|
||||
filePath := filepath.Join(tmpDir, filename)
|
||||
|
||||
line := fmt.Sprintf("%s | %-15s | %-40s | %-16s | %s\n",
|
||||
time.Now().Format("2006-01-02T15:04:05.000000"),
|
||||
feature,
|
||||
scenario,
|
||||
action,
|
||||
details,
|
||||
)
|
||||
|
||||
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err := file.WriteString(line); err != nil {
|
||||
return
|
||||
}
|
||||
file.Sync()
|
||||
}
|
||||
Reference in New Issue
Block a user