diff --git a/tests/msc4140/delayed_event_test.go b/tests/msc4140/delayed_event_test.go index 1d9f6db25..e974d759e 100644 --- a/tests/msc4140/delayed_event_test.go +++ b/tests/msc4140/delayed_event_test.go @@ -62,6 +62,34 @@ 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{}{})}, + {"non-integer delay_ms", map[string]interface{}{"delay_ms": 1.5, "content": map[string]interface{}{}}}, + {"string delay_ms", map[string]interface{}{"delay_ms": "1000", "content": map[string]interface{}{}}}, + {"missing content", map[string]interface{}{"delay_ms": 1000}}, + } { + 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 @@ -75,15 +103,15 @@ 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") @@ -91,8 +119,8 @@ func TestDelayedEvents(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{ @@ -146,11 +174,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 @@ -254,11 +281,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") @@ -308,11 +334,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") @@ -364,11 +389,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") @@ -437,9 +461,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++ @@ -471,11 +494,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++ } @@ -532,18 +554,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 {