diff --git a/tests/room_timestamp_to_event_test.go b/tests/room_timestamp_to_event_test.go index 125f6606..fbc83e22 100644 --- a/tests/room_timestamp_to_event_test.go +++ b/tests/room_timestamp_to_event_test.go @@ -56,6 +56,9 @@ func TestJumpToDateEndpoint(t *testing.T) { t.Run("should find nothing before the earliest timestamp", func(t *testing.T) { t.Parallel() timeBeforeRoomCreation := time.Now() + // Guard so createRoom cannot share this sample's millisecond; a + // backward search there would return m.room.create instead of nothing. + time.Sleep(tsBoundaryGuard) roomID, _, _ := createTestRoom(t, alice) mustCheckEventisReturnedForTime(t, alice, roomID, timeBeforeRoomCreation, "b", "") }) @@ -76,6 +79,9 @@ func TestJumpToDateEndpoint(t *testing.T) { deployment.GetFullyQualifiedHomeserverName(t, "hs1"), }) + // Guard so the join cannot share a millisecond with the messages below. + time.Sleep(tsBoundaryGuard) + // Send a couple messages with the same timestamp after the other test // messages in the room. timeBeforeMessageCreation := time.Now() @@ -98,6 +104,9 @@ func TestJumpToDateEndpoint(t *testing.T) { deployment.GetFullyQualifiedHomeserverName(t, "hs1"), }) + // Guard so the join cannot share a millisecond with the messages below. + time.Sleep(tsBoundaryGuard) + // Send a couple messages with the same timestamp after the other test // messages in the room. timeBeforeMessageCreation := time.Now() @@ -113,6 +122,7 @@ func TestJumpToDateEndpoint(t *testing.T) { t.Run("should not be able to query a private room you are not a member of", func(t *testing.T) { t.Parallel() timeBeforeRoomCreation := time.Now() + time.Sleep(tsBoundaryGuard) // Alice will create the private room roomID := alice.MustCreateRoom(t, map[string]interface{}{ @@ -141,6 +151,7 @@ func TestJumpToDateEndpoint(t *testing.T) { t.Run("should not be able to query a public room you are not a member of", func(t *testing.T) { t.Parallel() timeBeforeRoomCreation := time.Now() + time.Sleep(tsBoundaryGuard) // Alice will create the public room roomID := alice.MustCreateRoom(t, map[string]interface{}{ @@ -187,6 +198,7 @@ func TestJumpToDateEndpoint(t *testing.T) { t.Run("when looking backwards before the room was created, should be able to find event that was imported", func(t *testing.T) { t.Parallel() timeBeforeRoomCreation := time.Now() + time.Sleep(tsBoundaryGuard) roomID, _, _ := createTestRoom(t, alice) // Join from the application service bridge user so we can use it to send @@ -331,6 +343,16 @@ type eventTime struct { AfterTimestamp time.Time } +// tsBoundaryGuard is a pause inserted around (before and after) where we create events +// so that `time.Now()` samples and subsequent event `origin_server_ts` don't collide at +// the same millisecond granularity. /timestamp_to_event returns the boundary event +// inclusively (forward picks the earliest event with ts >= query, backward picks the +// latest with ts <= query), so a shared millisecond between events means the wrong +// event can be picked. Adding one whole millisecond to a timestamp always carries it +// into the next millisecond bucket, so 1ms is enough to separate the sample from every +// event stamped after the pause. +const tsBoundaryGuard = 1 * time.Millisecond + func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, eventB *eventTime) { t.Helper() @@ -339,6 +361,7 @@ func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, event }) timeBeforeEventA := time.Now() + time.Sleep(tsBoundaryGuard) eventAID := c.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ @@ -346,8 +369,12 @@ func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, event "body": "Message A", }, }) - timeAfterEventA := time.Now() + // timeBeforeEventB doubles as eventA's after-timestamp, so guard it on + // both sides to keep it between the two events. + time.Sleep(tsBoundaryGuard) + timeBeforeEventB := time.Now() + time.Sleep(tsBoundaryGuard) eventBID := c.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ @@ -355,10 +382,12 @@ func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, event "body": "Message B", }, }) + + time.Sleep(tsBoundaryGuard) timeAfterEventB := time.Now() - eventA = &eventTime{EventID: eventAID, BeforeTimestamp: timeBeforeEventA, AfterTimestamp: timeAfterEventA} - eventB = &eventTime{EventID: eventBID, BeforeTimestamp: timeAfterEventA, AfterTimestamp: timeAfterEventB} + eventA = &eventTime{EventID: eventAID, BeforeTimestamp: timeBeforeEventA, AfterTimestamp: timeBeforeEventB} + eventB = &eventTime{EventID: eventBID, BeforeTimestamp: timeBeforeEventB, AfterTimestamp: timeAfterEventB} return roomID, eventA, eventB }