package database import ( "bufio" "bytes" "context" "io" "os" "sort" "sync" "testing" "git.mleku.dev/mleku/nostr/encoders/event" "git.mleku.dev/mleku/nostr/encoders/event/examples" "lol.mleku.dev" "lol.mleku.dev/log" ) // Shared test fixtures - initialized once in TestMain var ( sharedDB *D sharedDBDir string sharedDBCtx context.Context sharedDBCancel context.CancelFunc sharedDBOnce sync.Once sharedEvents []*event.E // Events that were successfully saved sharedSetupError error ) // initSharedDB initializes the shared test database with seeded data. // This is called once and shared across all tests that need seeded data. func initSharedDB() { sharedDBOnce.Do(func() { var err error // Create a temporary directory for the shared database sharedDBDir, err = os.MkdirTemp("", "shared-test-db-*") if err != nil { sharedSetupError = err return } // Create a context for the database sharedDBCtx, sharedDBCancel = context.WithCancel(context.Background()) // Initialize the database sharedDB, err = New(sharedDBCtx, sharedDBCancel, sharedDBDir, "info") if err != nil { sharedSetupError = err return } // Seed the database with events from examples.Cache scanner := bufio.NewScanner(bytes.NewBuffer(examples.Cache)) scanner.Buffer(make([]byte, 0, 1_000_000_000), 1_000_000_000) var events []*event.E for scanner.Scan() { b := scanner.Bytes() ev := event.New() if _, err = ev.Unmarshal(b); err != nil { continue } events = append(events, ev) } // Sort events by CreatedAt for consistent processing sort.Slice(events, func(i, j int) bool { return events[i].CreatedAt < events[j].CreatedAt }) // Save events to the database for _, ev := range events { if _, err = sharedDB.SaveEvent(sharedDBCtx, ev); err != nil { continue // Skip invalid events } sharedEvents = append(sharedEvents, ev) } }) } // GetSharedDB returns the shared test database. // Returns nil if testing.Short() is set or if setup failed. func GetSharedDB(t *testing.T) (*D, context.Context) { if testing.Short() { t.Skip("skipping test that requires seeded database in short mode") } initSharedDB() if sharedSetupError != nil { t.Fatalf("Failed to initialize shared database: %v", sharedSetupError) } return sharedDB, sharedDBCtx } // GetSharedEvents returns the events that were successfully saved to the shared database. func GetSharedEvents(t *testing.T) []*event.E { if testing.Short() { t.Skip("skipping test that requires seeded events in short mode") } initSharedDB() if sharedSetupError != nil { t.Fatalf("Failed to initialize shared database: %v", sharedSetupError) } return sharedEvents } // findEventWithTag finds an event with a single-character tag key and at least 2 elements. // Returns nil if no suitable event is found. func findEventWithTag(events []*event.E) *event.E { for _, ev := range events { if ev.Tags != nil && ev.Tags.Len() > 0 { for _, tg := range *ev.Tags { if tg.Len() >= 2 && len(tg.Key()) == 1 { return ev } } } } return nil } func TestMain(m *testing.M) { // Disable all logging during tests unless explicitly enabled if os.Getenv("TEST_LOG") == "" { // Set log level to Off to suppress all logs lol.SetLogLevel("off") // Also redirect output to discard lol.Writer = io.Discard // Disable all log printers log.T = lol.GetNullPrinter() log.D = lol.GetNullPrinter() log.I = lol.GetNullPrinter() log.W = lol.GetNullPrinter() log.E = lol.GetNullPrinter() log.F = lol.GetNullPrinter() // Also suppress badger logs os.Setenv("BADGER_LOG_LEVEL", "CRITICAL") } // Run tests code := m.Run() // Cleanup shared database if sharedDBCancel != nil { sharedDBCancel() } if sharedDB != nil { sharedDB.Close() } if sharedDBDir != "" { os.RemoveAll(sharedDBDir) } os.Exit(code) }