398 lines
9.4 KiB
Go
398 lines
9.4 KiB
Go
package leveldb
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"m8sh.su/x/m8sh/database"
|
|
)
|
|
|
|
func TestChat_Put(t *testing.T) {
|
|
db, cleanup := openDB(t)
|
|
defer cleanup()
|
|
|
|
chat := db.Chat()
|
|
user := "masha@d1.com"
|
|
|
|
t.Run("put incoming message", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Content: []byte("hello"),
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("put outgoing message", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: user,
|
|
To: "alice@d3.net",
|
|
Content: []byte("hey"),
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("put message with attachments", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Content: []byte("check this"),
|
|
Date: time.Now(),
|
|
Attachments: []database.Attachment{
|
|
{Filename: "img.png", Size: 512, MimeType: "image/png"},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("put empty content", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("put message with signature", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Content: []byte("signed"),
|
|
Date: time.Now(),
|
|
Signature: []byte("sig123"),
|
|
})
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("put group message", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Group: []string{user, "alice@d3.net", "carol@d4.org"},
|
|
Content: []byte("group chat"),
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestChat_Dialogues(t *testing.T) {
|
|
db, cleanup := openDB(t)
|
|
defer cleanup()
|
|
|
|
chat := db.Chat()
|
|
user := "masha@d1.com"
|
|
|
|
t.Run("empty dialogues", func(t *testing.T) {
|
|
list, err := chat.Dialogues(user, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Empty(t, list)
|
|
})
|
|
|
|
t.Run("single dialogue", func(t *testing.T) {
|
|
now := time.Now()
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Content: []byte("hello"),
|
|
Date: now,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Dialogues(user, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 1)
|
|
require.Equal(t, "bob@d2.io", list[0].Contact)
|
|
require.Equal(t, []byte("hello"), list[0].LastContent)
|
|
require.Equal(t, 1, list[0].UnreadCount)
|
|
})
|
|
|
|
t.Run("multiple messages increment unread", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: "bob@d2.io",
|
|
To: user,
|
|
Content: []byte("second"),
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Dialogues(user, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 1)
|
|
require.Equal(t, 2, list[0].UnreadCount)
|
|
})
|
|
|
|
t.Run("filter after time", func(t *testing.T) {
|
|
past := time.Now().Add(-time.Hour)
|
|
err := chat.Put(user, database.Message{
|
|
From: "carol@d4.org",
|
|
To: user,
|
|
Content: []byte("old"),
|
|
Date: past,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Dialogues(user, 10, time.Now().Add(-time.Minute))
|
|
require.NoError(t, err)
|
|
for _, d := range list {
|
|
require.NotEqual(t, "carol@d4.org", d.Contact)
|
|
}
|
|
})
|
|
|
|
t.Run("limit respected", func(t *testing.T) {
|
|
list, err := chat.Dialogues(user, 1, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 1)
|
|
})
|
|
|
|
t.Run("user isolation", func(t *testing.T) {
|
|
list, err := chat.Dialogues("other@d5.io", 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Empty(t, list)
|
|
})
|
|
}
|
|
|
|
func TestChat_Messages(t *testing.T) {
|
|
db, cleanup := openDB(t)
|
|
defer cleanup()
|
|
|
|
chat := db.Chat()
|
|
user := "masha@d1.com"
|
|
contact := "bob@d2.io"
|
|
|
|
t.Run("empty messages", func(t *testing.T) {
|
|
list, err := chat.Messages(user, contact, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Empty(t, list)
|
|
})
|
|
|
|
t.Run("messages for contact", func(t *testing.T) {
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("msg1"),
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Messages(user, contact, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 1)
|
|
require.Equal(t, []byte("msg1"), list[0].Content)
|
|
})
|
|
|
|
t.Run("filter after time", func(t *testing.T) {
|
|
contact := "filter-test@x.com"
|
|
now := time.Now()
|
|
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("recent"),
|
|
Date: now,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
past := now.Add(-time.Hour)
|
|
err = chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("old"),
|
|
Date: past,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Messages(user, contact, 10, now.Add(-time.Minute))
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 1)
|
|
require.Equal(t, []byte("recent"), list[0].Content)
|
|
})
|
|
|
|
t.Run("limit respected", func(t *testing.T) {
|
|
for i := 0; i < 5; i++ {
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("msg"),
|
|
Date: time.Now().Add(time.Duration(i) * time.Second),
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
list, err := chat.Messages(user, contact, 2, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 2)
|
|
})
|
|
|
|
t.Run("contact isolation", func(t *testing.T) {
|
|
list, err := chat.Messages(user, "unknown@d5.io", 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Empty(t, list)
|
|
})
|
|
}
|
|
|
|
func TestChat_MarkSeen(t *testing.T) {
|
|
db, cleanup := openDB(t)
|
|
defer cleanup()
|
|
|
|
chat := db.Chat()
|
|
user := "masha@d1.com"
|
|
contact := "bob@d2.io"
|
|
now := time.Now()
|
|
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("unread"),
|
|
Date: now,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("mark seen", func(t *testing.T) {
|
|
err := chat.MarkSeen(user, contact, now)
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Messages(user, contact, 1, time.Time{})
|
|
require.NoError(t, err)
|
|
require.True(t, list[0].Seen)
|
|
})
|
|
|
|
t.Run("mark seen twice is idempotent", func(t *testing.T) {
|
|
err := chat.MarkSeen(user, contact, now)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("mark seen non-existing returns ErrNotFound", func(t *testing.T) {
|
|
err := chat.MarkSeen(user, "unknown@d5.io", now)
|
|
require.ErrorIs(t, err, database.ErrNotFound)
|
|
})
|
|
}
|
|
|
|
func TestChat_Delete(t *testing.T) {
|
|
db, cleanup := openDB(t)
|
|
defer cleanup()
|
|
|
|
chat := db.Chat()
|
|
user := "masha@d1.com"
|
|
contact := "bob@d2.io"
|
|
now := time.Now()
|
|
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("delete me"),
|
|
Date: now,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("delete existing", func(t *testing.T) {
|
|
err := chat.Delete(user, contact, now)
|
|
require.NoError(t, err)
|
|
|
|
list, err := chat.Messages(user, contact, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
require.Empty(t, list)
|
|
})
|
|
|
|
t.Run("delete non-existing returns ErrNotFound", func(t *testing.T) {
|
|
err := chat.Delete(user, "unknown@d5.io", now)
|
|
require.ErrorIs(t, err, database.ErrNotFound)
|
|
})
|
|
|
|
t.Run("delete twice returns ErrNotFound", func(t *testing.T) {
|
|
err := chat.Delete(user, contact, now)
|
|
require.ErrorIs(t, err, database.ErrNotFound)
|
|
})
|
|
|
|
t.Run("delete last message updates dialogue", func(t *testing.T) {
|
|
contact := "dialog-update@test.com"
|
|
first := time.Now()
|
|
second := first.Add(time.Second)
|
|
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("first"),
|
|
Date: first,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
err = chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("second"),
|
|
Date: second,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Delete the last message.
|
|
err = chat.Delete(user, contact, second)
|
|
require.NoError(t, err)
|
|
|
|
// Dialogue should now show the first message.
|
|
dialogues, err := chat.Dialogues(user, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
var found bool
|
|
for _, d := range dialogues {
|
|
if d.Contact == contact {
|
|
require.Equal(t, []byte("first"), d.LastContent)
|
|
found = true
|
|
}
|
|
}
|
|
require.True(t, found, "dialogue should still exist")
|
|
})
|
|
|
|
t.Run("delete only message removes dialogue", func(t *testing.T) {
|
|
contact := "remove-dialog@test.com"
|
|
msgTime := time.Now()
|
|
|
|
err := chat.Put(user, database.Message{
|
|
From: contact,
|
|
To: user,
|
|
Content: []byte("only"),
|
|
Date: msgTime,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Delete the only message.
|
|
err = chat.Delete(user, contact, msgTime)
|
|
require.NoError(t, err)
|
|
|
|
// Dialogue should be gone.
|
|
dialogues, err := chat.Dialogues(user, 10, time.Time{})
|
|
require.NoError(t, err)
|
|
for _, d := range dialogues {
|
|
require.NotEqual(t, contact, d.Contact)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestChat_AfterClose(t *testing.T) {
|
|
path := t.TempDir() + "/db"
|
|
db, err := New(path)
|
|
require.NoError(t, err)
|
|
|
|
chat := db.Chat()
|
|
err = chat.Put("masha@d1.com", database.Message{
|
|
From: "bob@d2.io",
|
|
To: "masha@d1.com",
|
|
Content: []byte("data"),
|
|
Date: time.Now(),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, db.Close())
|
|
|
|
require.NotPanics(t, func() {
|
|
chat.Put("masha@d1.com", database.Message{From: "x", To: "y", Date: time.Now()})
|
|
chat.Dialogues("masha@d1.com", 10, time.Time{})
|
|
chat.Messages("masha@d1.com", "bob@d2.io", 10, time.Time{})
|
|
chat.MarkSeen("masha@d1.com", "bob@d2.io", time.Now())
|
|
chat.Delete("masha@d1.com", "bob@d2.io", time.Now())
|
|
})
|
|
}
|