package server import ( "bytes" "os" "path/filepath" "testing" ) // A chat deleted takes with it what the user attached to it: the text of // its files lives in the messages, and must be gone from the database // files too - not just from the tables (SQLite leaves deleted rows in its // free pages and in the write-ahead log). func TestDeleteChatWipesAttachments(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "t.db") db, err := OpenDB(path) if err != nil { t.Fatal(err) } s, err := New(Options{DB: db, DistDir: t.TempDir()}) if err != nil { t.Fatal(err) } hash, _ := hashPassword("Passw0rd12345") if err := db.CreateAdmin("adm", hash); err != nil { t.Fatal(err) } adm, _ := db.AdminByUsername("adm") me := adm.ID const secret = "TOP-SECRET-CONTENT-OF-AN-ATTACHED-FILE-7731" chat := s.aiNewChat(me) other := s.aiNewChat(me) s.aiAppendTo(me, chat, "user", "посмотри\n\n[Вложение: notes.txt]\nСодержимое файла:\n"+secret) s.aiAppendTo(me, chat, "result", "Картинка готова [картинка: https://s2.x-grk.com/uploads/userphoto/ai/zzz-7731.png]") s.aiAppendTo(me, other, "user", "другой чат, остаётся") s.aiDeleteChat(me, chat) var n int _ = db.sql.QueryRow(`SELECT COUNT(*) FROM ai_messages WHERE chat_id = ?`, chat).Scan(&n) if n != 0 { t.Fatalf("%d messages of the deleted chat remain", n) } _ = db.sql.QueryRow(`SELECT COUNT(*) FROM ai_messages WHERE chat_id = ?`, other).Scan(&n) if n != 1 { t.Fatalf("the other chat has %d messages, want 1", n) } for _, f := range []string{path, path + "-wal"} { b, _ := os.ReadFile(f) if bytes.Contains(b, []byte(secret)) || bytes.Contains(b, []byte("zzz-7731")) { t.Fatalf("the deleted chat's content is still in %s", filepath.Base(f)) } } } // The oldest chats go past the limit the same way: nothing of them is kept. func TestOldChatsWipedToo(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "t.db") db, err := OpenDB(path) if err != nil { t.Fatal(err) } s, err := New(Options{DB: db, DistDir: t.TempDir()}) if err != nil { t.Fatal(err) } hash, _ := hashPassword("Passw0rd12345") if err := db.CreateAdmin("adm", hash); err != nil { t.Fatal(err) } adm, _ := db.AdminByUsername("adm") me := adm.ID first := s.aiNewChat(me) s.aiAppendTo(me, first, "user", "[Вложение: a.txt]\nСодержимое файла:\nOLD-ATTACHMENT-TEXT-5512") for i := 0; i < aiChatsKeep; i++ { s.aiNewChat(me) } if s.aiOwns(me, first) { t.Fatal("the oldest chat is kept past the limit") } for _, f := range []string{path, path + "-wal"} { b, _ := os.ReadFile(f) if bytes.Contains(b, []byte("OLD-ATTACHMENT-TEXT-5512")) { t.Fatalf("the old chat's content is still in %s", filepath.Base(f)) } } }