143 lines
3.7 KiB
Go
Raw Permalink Normal View History

package testutils
import (
"encoding/json"
"fmt"
"sync"
"testing"
2021-10-26 10:01:45 +01:00
"time"
"github.com/matrix-org/gomatrixserverlib/spec"
)
// Common functions between testing.T and testing.B
type TestBenchInterface interface {
Fatalf(s string, args ...interface{})
Errorf(s string, args ...interface{})
add extensions for typing and receipts; bugfixes and additional perf improvements Features: - Add `typing` extension. - Add `receipts` extension. - Add comprehensive prometheus `/metrics` activated via `SYNCV3_PROM`. - Add `SYNCV3_PPROF` support. - Add `by_notification_level` sort order. - Add `include_old_rooms` support. - Add support for `$ME` and `$LAZY`. - Add correct filtering when `*,*` is used as `required_state`. - Add `num_live` to each room response to indicate how many timeline entries are live. Bug fixes: - Use a stricter comparison function on ranges: fixes an issue whereby UTs fail on go1.19 due to change in sorting algorithm. - Send back an `errcode` on HTTP errors (e.g expired sessions). - Remove `unsigned.txn_id` on insertion into the DB. Otherwise other users would see other users txn IDs :( - Improve range delta algorithm: previously it didn't handle cases like `[0,20] -> [20,30]` and would panic. - Send HTTP 400 for invalid range requests. - Don't publish no-op unread counts which just adds extra noise. - Fix leaking DB connections which could eventually consume all available connections. - Ensure we always unblock WaitUntilInitialSync even on invalid access tokens. Other code relies on WaitUntilInitialSync() actually returning at _some_ point e.g on startup we have N workers which bound the number of concurrent pollers made at any one time, we need to not just hog a worker forever. Improvements: - Greatly improve startup times of sync3 handlers by improving `JoinedRoomsTracker`: a modest amount of data would take ~28s to create the handler, now it takes 4s. - Massively improve initial initial v3 sync times, by refactoring `JoinedRoomsTracker`, from ~47s to <1s. - Add `SlidingSyncUntil...` in tests to reduce races. - Tweak the API shape of JoinedUsersForRoom to reduce state block processing time for large rooms from 63s to 39s. - Add trace task for initial syncs. - Include the proxy version in UA strings. - HTTP errors now wait 1s before returning to stop clients tight-looping on error. - Pending event buffer is now 2000. - Index the room ID first to cull the most events when returning timeline entries. Speeds up `SelectLatestEventsBetween` by a factor of 8. - Remove cancelled `m.room_key_requests` from the to-device inbox. Cuts down the amount of events in the inbox by ~94% for very large (20k+) inboxes, ~50% for moderate sized (200 events) inboxes. Adds book-keeping to remember the unacked to-device position for each client.
2022-12-14 18:53:55 +00:00
Logf(s string, args ...interface{})
Helper()
Name() string
}
var (
eventIDCounter = 0
eventIDMu sync.Mutex
)
type eventMock struct {
Type string `json:"type"`
StateKey *string `json:"state_key,omitempty"`
Sender string `json:"sender"`
Content interface{} `json:"content"`
EventID string `json:"event_id"`
OriginServerTS int64 `json:"origin_server_ts"`
Unsigned interface{} `json:"unsigned,omitempty"`
}
func generateEventID(t TestBenchInterface) string {
eventIDMu.Lock()
defer eventIDMu.Unlock()
eventIDCounter++
// we need to mux in the test name bleurgh because when run using `go test ./...` each
// package's tests run in parallel but with a shared database when run on Github Actions
return fmt.Sprintf("$event_%d_%s", eventIDCounter, t.Name())
}
type eventMockModifier func(e *eventMock)
func WithTimestamp(ts time.Time) eventMockModifier {
return func(e *eventMock) {
e.OriginServerTS = int64(spec.AsTimestamp(ts))
}
}
func WithUnsigned(unsigned interface{}) eventMockModifier {
return func(e *eventMock) {
e.Unsigned = unsigned
}
}
2022-07-12 15:12:02 +01:00
// Create a new m.room.member state event with membership: join for the given userID.
func NewJoinEvent(t TestBenchInterface, userID string, modifiers ...eventMockModifier) json.RawMessage {
return NewStateEvent(t, "m.room.member", userID, userID, map[string]interface{}{
"membership": "join",
}, modifiers...)
}
2023-06-06 20:39:57 +01:00
func NewMessageEvent(t TestBenchInterface, userID, text string, modifiers ...eventMockModifier) json.RawMessage {
return NewEvent(t, "m.room.message", userID, map[string]interface{}{
"msgtype": "m.text",
"body": text,
2023-06-06 20:39:57 +01:00
}, modifiers...)
}
func NewStateEvent(t TestBenchInterface, evType, stateKey, sender string, content interface{}, modifiers ...eventMockModifier) json.RawMessage {
t.Helper()
e := &eventMock{
Type: evType,
StateKey: &stateKey,
Sender: sender,
Content: content,
EventID: generateEventID(t),
OriginServerTS: int64(spec.AsTimestamp(time.Now())),
}
for _, m := range modifiers {
m(e)
2021-10-26 10:01:45 +01:00
}
j, err := json.Marshal(&e)
if err != nil {
t.Fatalf("failed to make event JSON: %s", err)
}
return j
}
func NewEvent(t TestBenchInterface, evType, sender string, content interface{}, modifiers ...eventMockModifier) json.RawMessage {
t.Helper()
e := &eventMock{
Type: evType,
Sender: sender,
Content: content,
EventID: generateEventID(t),
OriginServerTS: int64(spec.AsTimestamp(time.Now())),
}
for _, m := range modifiers {
m(e)
}
j, err := json.Marshal(&e)
if err != nil {
t.Fatalf("failed to make event JSON: %s", err)
}
return j
}
func NewAccountData(t *testing.T, evType string, content interface{}) json.RawMessage {
e := struct {
Type string `json:"type"`
Content interface{} `json:"content"`
}{
Type: evType,
Content: content,
}
j, err := json.Marshal(&e)
if err != nil {
t.Fatalf("NewAccountData: failed to make event JSON: %s", err)
}
return j
}
2023-06-07 13:58:44 +01:00
func SetTimestamp(t *testing.T, event json.RawMessage, ts time.Time) json.RawMessage {
parsed := eventMock{}
err := json.Unmarshal(event, &parsed)
if err != nil {
t.Errorf("Failed to parse eventMock: %s", err)
return nil
}
parsed.OriginServerTS = int64(spec.AsTimestamp(ts))
2023-06-07 13:58:44 +01:00
edited, err := json.Marshal(parsed)
if err != nil {
t.Errorf("Failed to serialise eventMock: %s", err)
return nil
}
return edited
}