diff --git a/services/horizon/internal/actions/helpers.go b/services/horizon/internal/actions/helpers.go index f4ddeb5b89..a2ce9675eb 100644 --- a/services/horizon/internal/actions/helpers.go +++ b/services/horizon/internal/actions/helpers.go @@ -223,7 +223,7 @@ func GetPageQuery(ledgerState *ledger.State, r *http.Request, opts ...Opt) (db2. } if defaultTOID && pageQuery.Order == db2.OrderAscending { - if cursor == "" || errors.Is(validateCursorWithinHistory(ledgerState, pageQuery), &hProblem.BeforeHistory) { + if cursor == "" || errors.Is(validateCursor(ledgerState, pageQuery), &hProblem.BeforeHistory) { pageQuery.Cursor = toid.AfterLedger( ordered.Max(0, ledgerState.CurrentStatus().HistoryElder-1), ).String() @@ -566,6 +566,10 @@ func validateCursorWithinHistory(ledgerState *ledger.State, pq db2.PageQuery) er return nil } + return validateCursor(ledgerState, pq) +} + +func validateCursor(ledgerState *ledger.State, pq db2.PageQuery) error { var cursor int64 var err error diff --git a/services/horizon/internal/actions/helpers_test.go b/services/horizon/internal/actions/helpers_test.go index 05e840577e..b18a6b4b1f 100644 --- a/services/horizon/internal/actions/helpers_test.go +++ b/services/horizon/internal/actions/helpers_test.go @@ -345,7 +345,117 @@ func TestGetPageQueryCursorDefaultTOID(t *testing.T) { assert.Equal(t, "", pq.Cursor) assert.Equal(t, uint64(2), pq.Limit) assert.Equal(t, "desc", pq.Order) +} + +func TestPageQueryCursorFullHistory(t *testing.T) { + ledgerState := &ledger.State{} + ledgerState.SetHorizonStatus(ledger.HorizonStatus{ + HistoryLatest: 7000, + HistoryLatestClosedAt: time.Now(), + HistoryElder: 0, + ExpHistoryLatest: 7000, + }) + + ascReq := makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(200).String()), testURLParams()) + pq, err := GetPageQuery(ledgerState, ascReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(200).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + ascReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(200).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, ascReq) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(200).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + descReq := makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2&order=desc", toid.AfterLedger(200).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, descReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(200).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "desc", pq.Order) + + descReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2&order=desc", toid.AfterLedger(200).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, descReq) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(200).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "desc", pq.Order) +} + +func TestPageQueryCursorLimitedHistory(t *testing.T) { + ledgerState := &ledger.State{} + ledgerState.SetHorizonStatus(ledger.HorizonStatus{ + HistoryLatest: 7000, + HistoryLatestClosedAt: time.Now(), + HistoryElder: 300, + ExpHistoryLatest: 7000, + }) + + ascReq := makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(200).String()), testURLParams()) + pq, err := GetPageQuery(ledgerState, ascReq) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(200).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + ascReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(200).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, ascReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(299).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + ascReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(298).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, ascReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(299).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + ascReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(299).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, ascReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(299).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + ascReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(300).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, ascReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(300).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + ascReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2", toid.AfterLedger(301).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, ascReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(301).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "asc", pq.Order) + + descReq := makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2&order=desc", toid.AfterLedger(298).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, descReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(298).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "desc", pq.Order) + + descReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2&order=desc", toid.AfterLedger(320).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, descReq, DefaultTOID) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(320).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "desc", pq.Order) + + descReq = makeTestActionRequest(fmt.Sprintf("/foo-bar/blah?cursor=%s&limit=2&order=desc", toid.AfterLedger(298).String()), testURLParams()) + pq, err = GetPageQuery(ledgerState, descReq) + assert.NoError(t, err) + assert.Equal(t, toid.AfterLedger(298).String(), pq.Cursor) + assert.Equal(t, uint64(2), pq.Limit) + assert.Equal(t, "desc", pq.Order) } func TestGetString(t *testing.T) {