Files
m8sh/database/leveldb/users_test.go
T
2026-06-06 19:20:38 +03:00

194 lines
4.8 KiB
Go

package leveldb
import (
"encoding/binary"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"m8sh.su/x/m8sh/database"
)
func TestUsers_Create(t *testing.T) {
db, cleanup := openDB(t)
defer cleanup()
users := db.Users()
user := database.User{
Name: "masha@d1.com",
DisplayName: "Masha",
Bio: "test bio",
PublicKey: []byte("pubkey"),
Avatar: uuid.New(),
}
t.Run("create new user", func(t *testing.T) {
err := users.Create(user)
require.NoError(t, err)
})
t.Run("create duplicate returns ErrAlreadyExists", func(t *testing.T) {
err := users.Create(user)
require.ErrorIs(t, err, database.ErrAlreadyExists)
})
t.Run("create with empty name", func(t *testing.T) {
err := users.Create(database.User{Name: ""})
require.NoError(t, err)
})
}
func TestUsers_Get(t *testing.T) {
db, cleanup := openDB(t)
defer cleanup()
users := db.Users()
user := database.User{
Name: "masha@d1.com",
DisplayName: "Masha",
Bio: "test bio",
PublicKey: []byte("pubkey"),
Avatar: uuid.New(),
}
require.NoError(t, users.Create(user))
t.Run("get existing user", func(t *testing.T) {
got, err := users.Get("masha@d1.com")
require.NoError(t, err)
require.Equal(t, user.Name, got.Name)
require.Equal(t, user.DisplayName, got.DisplayName)
require.Equal(t, user.Bio, got.Bio)
require.Equal(t, user.PublicKey, got.PublicKey)
require.Equal(t, user.Avatar, got.Avatar)
})
t.Run("get non-existing user returns ErrNotFound", func(t *testing.T) {
_, err := users.Get("nonexistent@d1.com")
require.ErrorIs(t, err, database.ErrNotFound)
})
t.Run("get user with subscribers count", func(t *testing.T) {
// Write a valid total key for this user.
totalKey := key("masha@d1.com", prefixSubsTotal)
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], 42)
require.NoError(t, db.db.Put(totalKey, buf[:], nil))
got, err := users.Get("masha@d1.com")
require.NoError(t, err)
require.Equal(t, uint64(42), got.Subscribers)
})
t.Run("get user ignores corrupted total key", func(t *testing.T) {
// Write garbage as the total key.
totalKey := key("corrupted@d1.com", prefixSubsTotal)
require.NoError(t, db.db.Put(totalKey, []byte("not-a-number"), nil))
// Create the user.
require.NoError(t, users.Create(database.User{Name: "corrupted@d1.com"}))
// Get should still succeed, Subscribers will be 0 because binary.Uint64 on short data reads whatever it can.
got, err := users.Get("corrupted@d1.com")
require.NoError(t, err)
// 8 bytes not guaranteed, but it won't panic—just reads garbage as uint64.
_ = got.Subscribers
})
}
func TestUsers_Update(t *testing.T) {
db, cleanup := openDB(t)
defer cleanup()
users := db.Users()
user := database.User{
Name: "masha@d1.com",
DisplayName: "Masha",
}
require.NoError(t, users.Create(user))
t.Run("update existing user", func(t *testing.T) {
user.DisplayName = "Masha Updated"
user.Bio = "new bio"
err := users.Update("masha@d1.com", user)
require.NoError(t, err)
got, err := users.Get("masha@d1.com")
require.NoError(t, err)
require.Equal(t, "masha@d1.com", got.Name)
require.Equal(t, "Masha Updated", got.DisplayName)
require.Equal(t, "new bio", got.Bio)
})
t.Run("update non-existing user returns ErrNotFound", func(t *testing.T) {
err := users.Update("nonexistent@d1.com", user)
require.ErrorIs(t, err, database.ErrNotFound)
})
}
func TestUsers_Delete(t *testing.T) {
db, cleanup := openDB(t)
defer cleanup()
users := db.Users()
user := database.User{
Name: "masha@d1.com",
}
require.NoError(t, users.Create(user))
t.Run("delete existing user", func(t *testing.T) {
err := users.Delete("masha@d1.com")
require.NoError(t, err)
require.False(t, users.CheckExists("masha@d1.com"))
_, err = users.Get("masha@d1.com")
require.ErrorIs(t, err, database.ErrNotFound)
})
t.Run("delete non-existing user returns ErrNotFound", func(t *testing.T) {
err := users.Delete("nonexistent@d1.com")
require.ErrorIs(t, err, database.ErrNotFound)
})
}
func TestUsers_CheckExists(t *testing.T) {
db, cleanup := openDB(t)
defer cleanup()
users := db.Users()
user := database.User{
Name: "masha@d1.com",
}
require.NoError(t, users.Create(user))
t.Run("existing user returns true", func(t *testing.T) {
require.True(t, users.CheckExists("masha@d1.com"))
})
t.Run("non-existing user returns false", func(t *testing.T) {
require.False(t, users.CheckExists("nonexistent@d1.com"))
})
}
func TestUsers_AfterCloseReturnsError(t *testing.T) {
path := t.TempDir() + "/db"
db, err := New(path)
require.NoError(t, err)
users := db.Users()
require.NoError(t, users.Create(database.User{Name: "masha@d1.com"}))
require.NoError(t, db.Close())
_, err = users.Get("masha@d1.com")
require.Error(t, err)
require.False(t, users.CheckExists("masha@d1.com"))
}