@@ -218,6 +218,129 @@ func (s *E2EIntegrationSuite) TestLand_HappyPath_ReachesLanded() {
218218 "operating store should show request %s in terminal state landed" , sqid )
219219}
220220
221+ // TestList_ReturnsFilteredPagedSummaries verifies the customer-facing List RPC
222+ // against the full stack. Land writes the initial summary through the gateway,
223+ // later status updates arrive through the request-log topic, and List reads the
224+ // gateway-owned summary read model through the public RPC surface.
225+ func (s * E2EIntegrationSuite ) TestList_ReturnsFilteredPagedSummaries () {
226+ t := s .T ()
227+
228+ beforeWindow := s .land ("e2e-list-queue" , "github://uber/e2e-list/pull/100/abcdef0123456789abcdef0123456789abcdef00" )
229+ startTimeMs := time .Now ().UnixMilli () + 1
230+ windowTimer := time .NewTimer (time .Until (time .UnixMilli (startTimeMs )))
231+ <- windowTimer .C
232+ firstURI := "github://uber/e2e-list/pull/101/abcdef0123456789abcdef0123456789abcdef01"
233+ secondURI := "github://uber/e2e-list/pull/102/abcdef0123456789abcdef0123456789abcdef02"
234+ thirdURI := "github://uber/e2e-list/pull/103/abcdef0123456789abcdef0123456789abcdef03"
235+ otherURI := "github://uber/e2e-list-other/pull/201/abcdef0123456789abcdef0123456789abcdef03"
236+
237+ first := s .land ("e2e-list-queue" , firstURI )
238+ second := s .land ("e2e-list-queue" , secondURI )
239+ third := s .land ("e2e-list-queue" , thirdURI )
240+ otherQueue := s .land ("e2e-cancel-queue" , otherURI )
241+ endTimeMs := time .Now ().Add (time .Minute ).UnixMilli ()
242+
243+ resp := s .awaitListContains (& gatewaypb.ListRequest {
244+ Queue : "e2e-list-queue" ,
245+ StartTimeMs : startTimeMs ,
246+ EndTimeMs : endTimeMs ,
247+ PageSize : 10 ,
248+ }, first , second , third )
249+
250+ assert .NotContains (t , summarySQIDs (resp .Requests ), otherQueue ,
251+ "List should not return requests from a different queue" )
252+ assert .NotContains (t , summarySQIDs (resp .Requests ), beforeWindow ,
253+ "List should not return requests admitted before the time window" )
254+
255+ bySQID := make (map [string ]* gatewaypb.RequestSummary , len (resp .Requests ))
256+ for _ , summary := range resp .Requests {
257+ bySQID [summary .Sqid ] = summary
258+ }
259+
260+ firstSummary := bySQID [first ]
261+ require .NotNil (t , firstSummary , "List response should include %s" , first )
262+ assert .Equal (t , "e2e-list-queue" , firstSummary .Queue )
263+ assert .Equal (t , []string {firstURI }, firstSummary .ChangeUris )
264+ assert .NotEmpty (t , firstSummary .Status )
265+ assert .GreaterOrEqual (t , firstSummary .StartedAtMs , startTimeMs )
266+ assert .Less (t , firstSummary .StartedAtMs , endTimeMs )
267+ assert .GreaterOrEqual (t , firstSummary .UpdatedAtMs , firstSummary .StartedAtMs )
268+
269+ s .awaitStatus (first , entity .RequestStatusLanded )
270+ s .awaitStatus (second , entity .RequestStatusLanded )
271+ s .awaitStatus (third , entity .RequestStatusLanded )
272+
273+ landedResp := s .awaitListContains (& gatewaypb.ListRequest {
274+ Queue : "e2e-list-queue" ,
275+ StartTimeMs : startTimeMs ,
276+ EndTimeMs : endTimeMs ,
277+ Statuses : []string {string (entity .RequestStatusLanded )},
278+ PageSize : 10 ,
279+ }, first , second , third )
280+ for _ , summary := range landedResp .Requests {
281+ if summary .Sqid != first && summary .Sqid != second && summary .Sqid != third {
282+ continue
283+ }
284+ assert .Equal (t , string (entity .RequestStatusLanded ), summary .Status , "landed summary %s should report landed" , summary .Sqid )
285+ assert .Greater (t , summary .CompletedAtMs , int64 (0 ), "landed summary %s should have completion time" , summary .Sqid )
286+ }
287+
288+ var pagedSQIDs []string
289+ var pageToken string
290+ for {
291+ page := s .list (& gatewaypb.ListRequest {
292+ Queue : "e2e-list-queue" ,
293+ StartTimeMs : startTimeMs ,
294+ EndTimeMs : endTimeMs ,
295+ PageSize : 1 ,
296+ PageToken : pageToken ,
297+ Sort : gatewaypb .ListSort_ADMITTED_DESC ,
298+ })
299+ require .LessOrEqual (t , len (page .Requests ), 1 )
300+ if len (page .Requests ) == 1 {
301+ pagedSQIDs = append (pagedSQIDs , page .Requests [0 ].Sqid )
302+ }
303+ if page .NextPageToken == "" {
304+ break
305+ }
306+ pageToken = page .NextPageToken
307+ }
308+ assert .ElementsMatch (t , []string {first , second , third }, pagedSQIDs )
309+ assert .Len (t , mapFromStrings (pagedSQIDs ), len (pagedSQIDs ), "descending pagination should not return duplicates" )
310+ }
311+
312+ // TestList_ShowsCancelIntent verifies the List summary read model observes the
313+ // gateway-synchronous cancelling log written by Cancel. Terminal cancellation is
314+ // intentionally not asserted here because the e2e stack does not yet have a
315+ // deterministic pipeline pause; the terminal outcome can race with landing.
316+ func (s * E2EIntegrationSuite ) TestList_ShowsCancelIntent () {
317+ t := s .T ()
318+
319+ startTimeMs := time .Now ().Add (- time .Second ).UnixMilli ()
320+ sqid := s .land ("e2e-cancel-queue" , "github://uber/e2e-list-cancel/pull/301/abcdef0123456789abcdef0123456789abcdef04" )
321+ endTimeMs := time .Now ().Add (time .Minute ).UnixMilli ()
322+
323+ _ , err := s .gatewayClient .Cancel (s .ctx , & gatewaypb.CancelRequest {Sqid : sqid , Reason : "e2e list cancel test" })
324+ require .NoError (t , err , "Cancel failed" )
325+
326+ resp := s .list (& gatewaypb.ListRequest {
327+ Queue : "e2e-cancel-queue" ,
328+ StartTimeMs : startTimeMs ,
329+ EndTimeMs : endTimeMs ,
330+ Statuses : []string {string (entity .RequestStatusCancelling )},
331+ PageSize : 10 ,
332+ })
333+ var summary * gatewaypb.RequestSummary
334+ for _ , candidate := range resp .Requests {
335+ if candidate .Sqid == sqid {
336+ summary = candidate
337+ break
338+ }
339+ }
340+ require .NotNil (t , summary , "List should include %s with cancelling status immediately after Cancel" , sqid )
341+ assert .Equal (t , string (entity .RequestStatusCancelling ), summary .Status )
342+ }
343+
221344// TestCancelRequest_InvalidSqid verifies the gateway rejects an empty sqid
222345// synchronously before publishing anything to the cancel queue.
223346func (s * E2EIntegrationSuite ) TestCancelRequest_InvalidSqid () {
0 commit comments