@@ -2544,6 +2544,82 @@ func TestStreamOffset(t *testing.T) {
25442544
25452545 require .NoError (t , rdb .Del (ctx , streamKey ).Err ())
25462546 })
2547+
2548+ t .Run ("XPENDING with incomplete end ID should include the whole millisecond" , func (t * testing.T ) {
2549+ streamKey := "xpending-incomplete-end-test"
2550+ group := "grp"
2551+ consumer := "con"
2552+ ids := []string {"1-0" , "1-1" , "1-2" }
2553+
2554+ require .NoError (t , rdb .Del (ctx , streamKey ).Err ())
2555+ for i , id := range ids {
2556+ require .NoError (t , rdb .XAdd (ctx , & redis.XAddArgs {Stream : streamKey , ID : id , Values : []string {"f" , strconv .Itoa (i )}}).Err ())
2557+ }
2558+
2559+ require .NoError (t , rdb .XGroupCreateMkStream (ctx , streamKey , group , "0" ).Err ())
2560+ _ , err := rdb .XReadGroup (ctx , & redis.XReadGroupArgs {Group : group , Consumer : consumer , Streams : []string {streamKey , ">" }, Count : 10 }).Result ()
2561+ require .NoError (t , err )
2562+
2563+ result , err := rdb .Do (ctx , "XPENDING" , streamKey , group , "1" , "1" , "10" ).Result ()
2564+ require .NoError (t , err )
2565+ entries , ok := result .([]interface {})
2566+ require .True (t , ok )
2567+ require .Len (t , entries , 3 , "XPENDING 1 1 should include every pending entry in millisecond 1, matching Redis" )
2568+
2569+ for i , entry := range entries {
2570+ fields , ok := entry .([]interface {})
2571+ require .True (t , ok )
2572+ require .Len (t , fields , 4 )
2573+ gotID , ok := fields [0 ].(string )
2574+ require .True (t , ok )
2575+ require .Equal (t , ids [i ], gotID )
2576+ gotConsumer , ok := fields [1 ].(string )
2577+ require .True (t , ok )
2578+ require .Equal (t , consumer , gotConsumer )
2579+ require .GreaterOrEqual (t , fields [2 ], int64 (0 ))
2580+ require .EqualValues (t , 1 , fields [3 ])
2581+ }
2582+
2583+ require .NoError (t , rdb .Del (ctx , streamKey ).Err ())
2584+ })
2585+
2586+ t .Run ("XPENDING with exclusive start should match Redis" , func (t * testing.T ) {
2587+ streamKey := "xpending-exclusive-start-test"
2588+ group := "grp"
2589+ consumer := "con"
2590+ ids := []string {"1-0" , "1-1" , "1-2" }
2591+
2592+ require .NoError (t , rdb .Del (ctx , streamKey ).Err ())
2593+ for i , id := range ids {
2594+ require .NoError (t , rdb .XAdd (ctx , & redis.XAddArgs {Stream : streamKey , ID : id , Values : []string {"f" , strconv .Itoa (i )}}).Err ())
2595+ }
2596+
2597+ require .NoError (t , rdb .XGroupCreateMkStream (ctx , streamKey , group , "0" ).Err ())
2598+ _ , err := rdb .XReadGroup (ctx , & redis.XReadGroupArgs {Group : group , Consumer : consumer , Streams : []string {streamKey , ">" }, Count : 10 }).Result ()
2599+ require .NoError (t , err )
2600+
2601+ result , err := rdb .Do (ctx , "XPENDING" , streamKey , group , "(1-0" , "+" , "10" ).Result ()
2602+ require .NoError (t , err )
2603+ entries , ok := result .([]interface {})
2604+ require .True (t , ok )
2605+ require .Len (t , entries , 2 , "XPENDING (1-0 + 10 should exclude the first pending entry, matching Redis" )
2606+
2607+ for i , entry := range entries {
2608+ fields , ok := entry .([]interface {})
2609+ require .True (t , ok )
2610+ require .Len (t , fields , 4 )
2611+ gotID , ok := fields [0 ].(string )
2612+ require .True (t , ok )
2613+ require .Equal (t , ids [i + 1 ], gotID )
2614+ gotConsumer , ok := fields [1 ].(string )
2615+ require .True (t , ok )
2616+ require .Equal (t , consumer , gotConsumer )
2617+ require .GreaterOrEqual (t , fields [2 ], int64 (0 ))
2618+ require .EqualValues (t , 1 , fields [3 ])
2619+ }
2620+
2621+ require .NoError (t , rdb .Del (ctx , streamKey ).Err ())
2622+ })
25472623}
25482624
25492625func parseStreamEntryID (id string ) (ts int64 , seqNum int64 ) {
0 commit comments