Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 68 additions & 38 deletions tests/msc4140/delayed_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,31 @@ func TestDelayedEvents(t *testing.T) {
})
})

t.Run("cannot schedule a delayed event without a positive delay", func(t *testing.T) {
for i, tc := range []struct {
name string
body map[string]interface{}
}{
{"missing delay_ms", map[string]interface{}{"content": map[string]interface{}{}}},
{"zero delay_ms", getDelayedEventBody(0, map[string]interface{}{})},
{"negative delay_ms", getDelayedEventBody(-1, map[string]interface{}{})},
} {
t.Run(tc.name, func(t *testing.T) {
res := user.Do(
t,
"PUT",
getPathForDelayedEvent(roomID, eventType, fmt.Sprintf("txn-delayed-invalid-delay-%d", i)),
client.WithJSONBody(t, tc.body),
)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: 400,
})
})
}

matchDelayedEvents(t, user, delayedEventsNumberEqual(0))
})

// FIXME: Too much mixing of tests that should be more independent
t.Run("delayed message events are sent on timeout", func(t *testing.T) {
var res *http.Response
Expand All @@ -75,24 +100,24 @@ func TestDelayedEvents(t *testing.T) {

countKey := "count"
numEvents := 3
for i, delayStr := range []string{"700", "800", "900"} {
for i, delayMs := range []int64{700, 800, 900} {
body := getDelayedEventBody(delayMs, map[string]interface{}{
countKey: i + 1,
})
res = user.MustDo(
t,
"PUT",
getPathForSend(roomID, eventType, fmt.Sprintf(txnIdBase, i)),
client.WithJSONBody(t, map[string]interface{}{
countKey: i + 1,
}),
getDelayQueryParam(delayStr),
getPathForDelayedEvent(roomID, eventType, fmt.Sprintf(txnIdBase, i)),
client.WithJSONBody(t, body),
)
delayID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "delay_id")

t.Run("rerequesting delayed event path with the same txnID should have the same response", func(t *testing.T) {
res := user.MustDo(
t,
"PUT",
getPathForSend(roomID, eventType, fmt.Sprintf(txnIdBase, i)),
getDelayQueryParam(delayStr),
getPathForDelayedEvent(roomID, eventType, fmt.Sprintf(txnIdBase, i)),
client.WithJSONBody(t, body),
)
must.MatchResponse(t, res, match.HTTPResponse{
JSON: []match.JSON{
Expand Down Expand Up @@ -146,11 +171,10 @@ func TestDelayedEvents(t *testing.T) {
user.MustDo(
t,
"PUT",
getPathForState(roomID, eventType, stateKey),
client.WithJSONBody(t, map[string]interface{}{
getPathForDelayedEvent(roomID, eventType, "txn-delayed-state-timeout"),
client.WithJSONBody(t, getDelayedStateEventBody(900, stateKey, map[string]interface{}{
setterKey: setterExpected,
}),
getDelayQueryParam("900"),
})),
)

// Ensure that a delayed event is now scheduled
Expand Down Expand Up @@ -254,11 +278,10 @@ func TestDelayedEvents(t *testing.T) {
res = user.MustDo(
t,
"PUT",
getPathForState(roomID, eventType, stateKey),
client.WithJSONBody(t, map[string]interface{}{
getPathForDelayedEvent(roomID, eventType, "txn-delayed-state-cancel"),
client.WithJSONBody(t, getDelayedStateEventBody(1500, stateKey, map[string]interface{}{
setterKey: setterExpected,
}),
getDelayQueryParam("1500"),
})),
)
delayID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "delay_id")

Expand Down Expand Up @@ -308,11 +331,10 @@ func TestDelayedEvents(t *testing.T) {
res = user.MustDo(
t,
"PUT",
getPathForState(roomID, eventType, stateKey),
client.WithJSONBody(t, map[string]interface{}{
getPathForDelayedEvent(roomID, eventType, "txn-delayed-state-send"),
client.WithJSONBody(t, getDelayedStateEventBody(100000, stateKey, map[string]interface{}{
setterKey: setterExpected,
}),
getDelayQueryParam("100000"),
})),
)
delayID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "delay_id")

Expand Down Expand Up @@ -364,11 +386,10 @@ func TestDelayedEvents(t *testing.T) {
res = user.MustDo(
t,
"PUT",
getPathForState(roomID, eventType, stateKey),
client.WithJSONBody(t, map[string]interface{}{
getPathForDelayedEvent(roomID, eventType, "txn-delayed-state-restart"),
client.WithJSONBody(t, getDelayedStateEventBody(1500, stateKey, map[string]interface{}{
setterKey: setterExpected,
}),
getDelayQueryParam("1500"),
})),
)
delayID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "delay_id")

Expand Down Expand Up @@ -437,9 +458,8 @@ func TestDelayedEvents(t *testing.T) {
user.MustDo(
t,
"PUT",
getPathForState(roomID, eventType, stateKey1),
client.WithJSONBody(t, map[string]interface{}{}),
getDelayQueryParam("900"),
getPathForDelayedEvent(roomID, eventType, "txn-delayed-state-server-restart-1"),
client.WithJSONBody(t, getDelayedStateEventBody(900, stateKey1, map[string]interface{}{})),
)
numberOfDelayedEvents++

Expand Down Expand Up @@ -471,11 +491,10 @@ func TestDelayedEvents(t *testing.T) {
user.MustDo(
t,
"PUT",
getPathForDelayedEvent(roomID, eventType, fmt.Sprintf("txn-delayed-state-server-restart-%d", i+2)),
// Avoid clashing state keys as that would cancel previous delayed events on the
// same key (start at 2).
getPathForState(roomID, eventType, fmt.Sprintf("%d", i+2)),
client.WithJSONBody(t, map[string]interface{}{}),
getDelayQueryParam(fmt.Sprintf("%d", delay.Milliseconds())),
client.WithJSONBody(t, getDelayedStateEventBody(delay.Milliseconds(), fmt.Sprintf("%d", i+2), map[string]interface{}{})),
)
numberOfDelayedEvents++
}
Expand Down Expand Up @@ -532,18 +551,29 @@ func getPathForUpdateDelayedEvent(delayId string, action DelayedEventAction) []s
return append(getPathForDelayedEvents(), delayId, string(action))
}

func getPathForSend(roomID string, eventType string, txnId string) []string {
return []string{"_matrix", "client", "v3", "rooms", roomID, "send", eventType, txnId}
func getPathForDelayedEvent(roomID string, eventType string, txnID string) []string {
return []string{"_matrix", "client", "unstable", "org.matrix.msc4140", "rooms", roomID, "delayed_event", eventType, txnID}
}

func getPathForState(roomID string, eventType string, stateKey string) []string {
return []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, stateKey}
// getDelayedEventBody returns the body of a request to schedule a delayed message event
// through `getPathForDelayedEvent`.
func getDelayedEventBody(delayMs int64, content map[string]interface{}) map[string]interface{} {
return map[string]interface{}{
"delay_ms": delayMs,
"content": content,
}
}

func getDelayQueryParam(delayStr string) client.RequestOpt {
return client.WithQueries(url.Values{
"org.matrix.msc4140.delay": []string{delayStr},
})
// getDelayedStateEventBody returns the body of a request to schedule a delayed state event
// through `getPathForDelayedEvent`.
func getDelayedStateEventBody(delayMs int64, stateKey string, content map[string]interface{}) map[string]interface{} {
body := getDelayedEventBody(delayMs, content)
body["state_key"] = stateKey
return body
}

func getPathForState(roomID string, eventType string, stateKey string) []string {
return []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, stateKey}
}

func getDelayedEvents(t *testing.T, user *client.CSAPI) *http.Response {
Expand Down
Loading