package reportbuf_test import ( "os" "strings" "testing" "sneak.berlin/go/netwatch/internal/config" "sneak.berlin/go/netwatch/internal/globals" "sneak.berlin/go/netwatch/internal/logger" "sneak.berlin/go/netwatch/internal/reportbuf" "go.uber.org/fx" "go.uber.org/fx/fxtest" ) // TestFlushOnShutdown proves the flush-on-shutdown path: a // report appended after start but before the periodic flush // window must reach disk when the fx lifecycle stops. This is // the exact case that silent data loss on restart used to // destroy. func TestFlushOnShutdown(t *testing.T) { dir := t.TempDir() t.Setenv("DATA_DIR", dir) var buf *reportbuf.Buffer app := fxtest.New(t, fx.Provide( globals.New, logger.New, config.New, reportbuf.New, ), fx.Populate(&buf), ) app.RequireStart() err := buf.Append(map[string]string{"probe": "shutdown"}) if err != nil { t.Fatalf("append report: %v", err) } // RequireStop runs the reportbuf OnStop hook, which is the // only code path that flushes buffered reports on shutdown. app.RequireStop() if !hasReportFile(t, dir) { t.Fatal("no report file on disk after shutdown; " + "the buffered report was lost") } } func hasReportFile(t *testing.T, dir string) bool { t.Helper() entries, err := os.ReadDir(dir) if err != nil { t.Fatalf("read data dir: %v", err) } for _, e := range entries { if strings.HasSuffix(e.Name(), ".jsonl.zst") { info, statErr := e.Info() if statErr != nil { t.Fatalf("stat %s: %v", e.Name(), statErr) } if info.Size() > 0 { return true } } } return false }