-
Notifications
You must be signed in to change notification settings - Fork 69
TestJumpToDateEndpoint: Guard the parallel boundary subtests against millisecond collisions.
#872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
852d309
f445822
2070acf
549b181
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -56,6 +56,14 @@ func TestJumpToDateEndpoint(t *testing.T) { | |||||||||||||||||||||||||||||||||||
| t.Run("should find nothing before the earliest timestamp", func(t *testing.T) { | ||||||||||||||||||||||||||||||||||||
| t.Parallel() | ||||||||||||||||||||||||||||||||||||
| timeBeforeRoomCreation := time.Now() | ||||||||||||||||||||||||||||||||||||
| // /timestamp_to_event is millisecond-granular by spec, and the next | ||||||||||||||||||||||||||||||||||||
| // call (createTestRoom) writes an m.room.create whose | ||||||||||||||||||||||||||||||||||||
| // origin_server_ts can land in the same millisecond as the sample | ||||||||||||||||||||||||||||||||||||
| // above. A backward search at that millisecond inclusively returns | ||||||||||||||||||||||||||||||||||||
| // the create event when the test wants 404. Pause long enough that | ||||||||||||||||||||||||||||||||||||
| // every event the homeserver subsequently stamps is in a strictly | ||||||||||||||||||||||||||||||||||||
| // later millisecond. | ||||||||||||||||||||||||||||||||||||
| time.Sleep(tsBoundaryGuard) | ||||||||||||||||||||||||||||||||||||
| roomID, _, _ := createTestRoom(t, alice) | ||||||||||||||||||||||||||||||||||||
| mustCheckEventisReturnedForTime(t, alice, roomID, timeBeforeRoomCreation, "b", "") | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
|
|
@@ -76,6 +84,11 @@ func TestJumpToDateEndpoint(t *testing.T) { | |||||||||||||||||||||||||||||||||||
| deployment.GetFullyQualifiedHomeserverName(t, "hs1"), | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Keep the join in an earlier millisecond than the messages below so | ||||||||||||||||||||||||||||||||||||
| // it cannot win the boundary search; the topological tie-break is | ||||||||||||||||||||||||||||||||||||
| // what this subtest actually exercises. | ||||||||||||||||||||||||||||||||||||
| time.Sleep(tsBoundaryGuard) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Send a couple messages with the same timestamp after the other test | ||||||||||||||||||||||||||||||||||||
| // messages in the room. | ||||||||||||||||||||||||||||||||||||
| timeBeforeMessageCreation := time.Now() | ||||||||||||||||||||||||||||||||||||
|
|
@@ -98,6 +111,11 @@ func TestJumpToDateEndpoint(t *testing.T) { | |||||||||||||||||||||||||||||||||||
| deployment.GetFullyQualifiedHomeserverName(t, "hs1"), | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feels like we need (the join could be in the |
||||||||||||||||||||||||||||||||||||
| // Keep the join in an earlier millisecond than the messages below so | ||||||||||||||||||||||||||||||||||||
| // it cannot win the boundary search; the topological tie-break is | ||||||||||||||||||||||||||||||||||||
| // what this subtest actually exercises. | ||||||||||||||||||||||||||||||||||||
| time.Sleep(tsBoundaryGuard) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Send a couple messages with the same timestamp after the other test | ||||||||||||||||||||||||||||||||||||
| // messages in the room. | ||||||||||||||||||||||||||||||||||||
| timeBeforeMessageCreation := time.Now() | ||||||||||||||||||||||||||||||||||||
|
|
@@ -331,13 +349,32 @@ type eventTime struct { | |||||||||||||||||||||||||||||||||||
| AfterTimestamp time.Time | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // tsBoundaryGuard is the pause inserted around each time.Now() sample in this | ||||||||||||||||||||||||||||||||||||
| // file's helpers and subtests so that no homeserver-stamped origin_server_ts | ||||||||||||||||||||||||||||||||||||
| // can collide with the sample at 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 sample and event lets the wrong event win the boundary. | ||||||||||||||||||||||||||||||||||||
| // time.Sleep pauses for at least its argument, and adding a 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. | ||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra fluff (especially LLM sounding)
Suggested change
|
||||||||||||||||||||||||||||||||||||
| const tsBoundaryGuard = 1 * time.Millisecond | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, eventB *eventTime) { | ||||||||||||||||||||||||||||||||||||
| t.Helper() | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| roomID = c.MustCreateRoom(t, map[string]interface{}{ | ||||||||||||||||||||||||||||||||||||
| "preset": "public_chat", | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // MustCreateRoom returns once the homeserver has stamped the full | ||||||||||||||||||||||||||||||||||||
| // createRoom state batch (m.room.create through m.room.guest_access); | ||||||||||||||||||||||||||||||||||||
| // the trailing state event can share a millisecond with the time.Now() | ||||||||||||||||||||||||||||||||||||
| // below. Pausing here pushes the sample past that boundary so a forward | ||||||||||||||||||||||||||||||||||||
| // search anchored on timeBeforeEventA cannot land back on the createRoom | ||||||||||||||||||||||||||||||||||||
| // state. | ||||||||||||||||||||||||||||||||||||
| time.Sleep(tsBoundaryGuard) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| timeBeforeEventA := time.Now() | ||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
| eventAID := c.SendEventSynced(t, roomID, b.Event{ | ||||||||||||||||||||||||||||||||||||
| Type: "m.room.message", | ||||||||||||||||||||||||||||||||||||
|
|
@@ -348,6 +385,12 @@ func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, event | |||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
| timeAfterEventA := time.Now() | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
MadLittleMods marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||
| // eventB.BeforeTimestamp has to sit in a strictly later millisecond than | ||||||||||||||||||||||||||||||||||||
| // eventA, otherwise a forward search anchored there could land back on | ||||||||||||||||||||||||||||||||||||
| // eventA at a shared boundary millisecond. Nothing exercises this yet, but | ||||||||||||||||||||||||||||||||||||
| // keep the helper honest for callers that eventually will. | ||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not very relevant here
Suggested change
|
||||||||||||||||||||||||||||||||||||
| time.Sleep(tsBoundaryGuard) | ||||||||||||||||||||||||||||||||||||
| timeBeforeEventB := time.Now() | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+375
to
+376
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, we probably need a
Suggested change
(comment above could use work as well) |
||||||||||||||||||||||||||||||||||||
| eventBID := c.SendEventSynced(t, roomID, b.Event{ | ||||||||||||||||||||||||||||||||||||
| Type: "m.room.message", | ||||||||||||||||||||||||||||||||||||
| Content: map[string]interface{}{ | ||||||||||||||||||||||||||||||||||||
|
|
@@ -358,7 +401,7 @@ func createTestRoom(t *testing.T, c *client.CSAPI) (roomID string, eventA, event | |||||||||||||||||||||||||||||||||||
| timeAfterEventB := time.Now() | ||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| eventA = &eventTime{EventID: eventAID, BeforeTimestamp: timeBeforeEventA, AfterTimestamp: timeAfterEventA} | ||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for
Suggested change
Or we could keep with the previous pattern and just need to move the delays there instead and get rid of |
||||||||||||||||||||||||||||||||||||
| eventB = &eventTime{EventID: eventBID, BeforeTimestamp: timeAfterEventA, AfterTimestamp: timeAfterEventB} | ||||||||||||||||||||||||||||||||||||
| eventB = &eventTime{EventID: eventBID, BeforeTimestamp: timeBeforeEventB, AfterTimestamp: timeAfterEventB} | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| return roomID, eventA, eventB | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels like we need
time.Sleep(tsBoundaryGuard)here as wellIt's not strictly necessary here but for consistency sake and to make it clear that it's not the main part of the thing we're testing.