mirror of
https://github.com/matrix-org/dendrite
synced 2024-12-17 08:33:31 +00:00
c136a450d5
Fixes #2803 Also refactors the presence stream to not hit the database for every user, instead queries all users at once now.
136 lines
3.8 KiB
Go
136 lines
3.8 KiB
Go
package tables_test
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/matrix-org/gomatrixserverlib"
|
|
|
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
|
"github.com/matrix-org/dendrite/setup/config"
|
|
"github.com/matrix-org/dendrite/syncapi/storage/postgres"
|
|
"github.com/matrix-org/dendrite/syncapi/storage/sqlite3"
|
|
"github.com/matrix-org/dendrite/syncapi/storage/tables"
|
|
"github.com/matrix-org/dendrite/syncapi/types"
|
|
"github.com/matrix-org/dendrite/test"
|
|
)
|
|
|
|
func mustPresenceTable(t *testing.T, dbType test.DBType) (tables.Presence, func()) {
|
|
t.Helper()
|
|
connStr, close := test.PrepareDBConnectionString(t, dbType)
|
|
db, err := sqlutil.Open(&config.DatabaseOptions{
|
|
ConnectionString: config.DataSource(connStr),
|
|
}, sqlutil.NewExclusiveWriter())
|
|
if err != nil {
|
|
t.Fatalf("failed to open db: %s", err)
|
|
}
|
|
|
|
var tab tables.Presence
|
|
switch dbType {
|
|
case test.DBTypePostgres:
|
|
tab, err = postgres.NewPostgresPresenceTable(db)
|
|
case test.DBTypeSQLite:
|
|
var stream sqlite3.StreamIDStatements
|
|
if err = stream.Prepare(db); err != nil {
|
|
t.Fatalf("failed to prepare stream stmts: %s", err)
|
|
}
|
|
tab, err = sqlite3.NewSqlitePresenceTable(db, &stream)
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("failed to make new table: %s", err)
|
|
}
|
|
return tab, close
|
|
}
|
|
|
|
func TestPresence(t *testing.T) {
|
|
alice := test.NewUser(t)
|
|
bob := test.NewUser(t)
|
|
ctx := context.Background()
|
|
|
|
statusMsg := "Hello World!"
|
|
timestamp := gomatrixserverlib.AsTimestamp(time.Now())
|
|
|
|
var txn *sql.Tx
|
|
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
tab, closeDB := mustPresenceTable(t, dbType)
|
|
defer closeDB()
|
|
|
|
// Insert some presences
|
|
pos, err := tab.UpsertPresence(ctx, txn, alice.ID, &statusMsg, types.PresenceOnline, timestamp, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
wantPos := types.StreamPosition(1)
|
|
if pos != wantPos {
|
|
t.Errorf("expected pos to be %d, got %d", wantPos, pos)
|
|
}
|
|
pos, err = tab.UpsertPresence(ctx, txn, bob.ID, &statusMsg, types.PresenceOnline, timestamp, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
wantPos = 2
|
|
if pos != wantPos {
|
|
t.Errorf("expected pos to be %d, got %d", wantPos, pos)
|
|
}
|
|
|
|
// verify the expected max presence ID
|
|
maxPos, err := tab.GetMaxPresenceID(ctx, txn)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if maxPos != wantPos {
|
|
t.Errorf("expected max pos to be %d, got %d", wantPos, maxPos)
|
|
}
|
|
|
|
// This should increment the position
|
|
pos, err = tab.UpsertPresence(ctx, txn, bob.ID, &statusMsg, types.PresenceOnline, timestamp, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
wantPos = pos
|
|
if wantPos <= maxPos {
|
|
t.Errorf("expected pos to be %d incremented, got %d", wantPos, pos)
|
|
}
|
|
|
|
// This should return only Bobs status
|
|
presences, err := tab.GetPresenceAfter(ctx, txn, maxPos, gomatrixserverlib.EventFilter{Limit: 10})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if c := len(presences); c > 1 {
|
|
t.Errorf("expected only one presence, got %d", c)
|
|
}
|
|
|
|
// Validate the response
|
|
wantPresence := &types.PresenceInternal{
|
|
UserID: bob.ID,
|
|
Presence: types.PresenceOnline,
|
|
StreamPos: wantPos,
|
|
LastActiveTS: timestamp,
|
|
ClientFields: types.PresenceClientResponse{
|
|
LastActiveAgo: 0,
|
|
Presence: types.PresenceOnline.String(),
|
|
StatusMsg: &statusMsg,
|
|
},
|
|
}
|
|
if !reflect.DeepEqual(wantPresence, presences[bob.ID]) {
|
|
t.Errorf("unexpected presence result:\n%+v, want\n%+v", presences[bob.ID], wantPresence)
|
|
}
|
|
|
|
// Try getting presences for existing and non-existing users
|
|
getUsers := []string{alice.ID, bob.ID, "@doesntexist:test"}
|
|
presencesForUsers, err := tab.GetPresenceForUsers(ctx, nil, getUsers)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if len(presencesForUsers) >= len(getUsers) {
|
|
t.Errorf("expected less presences, but they are the same/more as requested: %d >= %d", len(presencesForUsers), len(getUsers))
|
|
}
|
|
})
|
|
|
|
}
|