package main import ( "os" "path/filepath" "testing" "time" "app_compartir/internal/cleaner" "app_compartir/internal/db" "app_compartir/internal/models" ) func TestGuestExpirationAndRegisteredPermanence(t *testing.T) { tmpDir, err := os.MkdirTemp("", "test_compartir_*") if err != nil { t.Fatalf("error creando tmpDir: %v", err) } defer os.RemoveAll(tmpDir) dbPath := filepath.Join(tmpDir, "test.db") uploadDir := filepath.Join(tmpDir, "uploads") database, err := db.Init(dbPath, uploadDir) if err != nil { t.Fatalf("error inicializando db: %v", err) } defer database.Close() // Crear archivo físico de prueba 1 (Guest vencido) guestExpiredFile := "guest_exp.txt" if err := os.WriteFile(filepath.Join(uploadDir, guestExpiredFile), []byte("contenido guest expirado"), 0644); err != nil { t.Fatalf("error escribiendo archivo guest: %v", err) } // Crear archivo físico de prueba 2 (Usuario Registrado de hace 48 horas) registeredOldFile := "user_old.txt" if err := os.WriteFile(filepath.Join(uploadDir, registeredOldFile), []byte("contenido usuario permanente"), 0644); err != nil { t.Fatalf("error escribiendo archivo usuario: %v", err) } // Crear usuario registrado en BD user := &models.User{ ID: "user_123", Provider: "webcontrol", ProviderID: "123", Email: "pablo@telcotronics.com", Name: "Pablo", CreatedAt: time.Now().Add(-48 * time.Hour), } if err := database.UpsertUser(user); err != nil { t.Fatalf("error creando usuario: %v", err) } // 1. Share de Invitado: expirado (subido hace 25 horas, venció hace 1 hora) pastExp := time.Now().Add(-1 * time.Hour) guestShare := &models.Share{ ID: "guest1", UserID: nil, UserDisplay: "Invitado", IsGuest: true, Type: "file", Title: "guest_doc.txt", StoredPath: guestExpiredFile, FileSize: 23, MimeType: "text/plain", CreatedAt: time.Now().Add(-25 * time.Hour), ExpiresAt: &pastExp, } if err := database.CreateShare(guestShare); err != nil { t.Fatalf("error guardando share guest: %v", err) } // 2. Share de Usuario Registrado: subido hace 48 horas, PERMANENTE (ExpiresAt = nil) regShare := &models.Share{ ID: "reg1", UserID: &user.ID, UserDisplay: user.Name, IsGuest: false, Type: "file", Title: "contrato_permanente.pdf", StoredPath: registeredOldFile, FileSize: 27, MimeType: "application/pdf", CreatedAt: time.Now().Add(-48 * time.Hour), ExpiresAt: nil, // PERMANENTE } if err := database.CreateShare(regShare); err != nil { t.Fatalf("error guardando share registrado: %v", err) } // Ejecutar Cleaner cleanerSvc := cleaner.New(database, uploadDir, 1*time.Minute) // Comprobar items a purgar expiredGuest, err := database.GetExpiredGuestShares() if err != nil { t.Fatalf("error consultando expirados: %v", err) } if len(expiredGuest) != 1 { t.Fatalf("esperado 1 archivo guest expirado, obtenido %d", len(expiredGuest)) } if expiredGuest[0].ID != "guest1" { t.Fatalf("esperado guest1 expirado, obtenido %s", expiredGuest[0].ID) } // Iniciar ciclo de purga cleanerSvc.Start() time.Sleep(100 * time.Millisecond) // esperar a que ejecute runPurge inicial cleanerSvc.Stop() // VERIFICACIÓN 1: El archivo de invitado DEBE haber sido borrado de BD y de disco purgedGuestShare, err := database.GetShare("guest1") if err == nil && purgedGuestShare != nil { t.Fatalf("El archivo de invitado NO debió existir en BD tras la purga") } if _, err := os.Stat(filepath.Join(uploadDir, guestExpiredFile)); !os.IsNotExist(err) { t.Fatalf("El archivo físico de invitado %s debió haber sido eliminado del disco", guestExpiredFile) } // VERIFICACIÓN 2: El archivo del usuario registrado DEBE permanencer intacto (BD y disco) stayedRegShare, err := database.GetShare("reg1") if err != nil || stayedRegShare == nil { t.Fatalf("El archivo de usuario registrado se borró por error: %v", err) } if stayedRegShare.ExpiresAt != nil { t.Fatalf("El archivo registrado no debe tener fecha de caducidad") } if _, err := os.Stat(filepath.Join(uploadDir, registeredOldFile)); os.IsNotExist(err) { t.Fatalf("El archivo físico registrado %s fue borrado erróneamente", registeredOldFile) } t.Log("✅ Test completado con éxito: Solo los datos de invitado caducan en 24h; los de usuarios registrados son permanentes.") }