code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/checkpoints_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package sqlstore_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"code.vegaprotocol.io/vega/datanode/entities"
    25  	"code.vegaprotocol.io/vega/datanode/sqlstore"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func addCheckpoint(t *testing.T, ctx context.Context, ns *sqlstore.Checkpoints, hash, blockHash string, blockHeight int64, block entities.Block,
    32  	seqNum uint64,
    33  ) entities.Checkpoint {
    34  	t.Helper()
    35  	c := entities.Checkpoint{
    36  		Hash:        hash,
    37  		BlockHash:   blockHash,
    38  		BlockHeight: blockHeight,
    39  		VegaTime:    block.VegaTime,
    40  		SeqNum:      seqNum,
    41  	}
    42  	ns.Add(ctx, c)
    43  	return c
    44  }
    45  
    46  func TestCheckpoints(t *testing.T) {
    47  	ctx := tempTransaction(t)
    48  
    49  	checkpointStore := sqlstore.NewCheckpoints(connectionSource)
    50  	blockStore := sqlstore.NewBlocks(connectionSource)
    51  	block1 := addTestBlock(t, ctx, blockStore)
    52  	block2 := addTestBlock(t, ctx, blockStore)
    53  
    54  	checkpoint1 := addCheckpoint(t, ctx, checkpointStore, "myHash", "myBlockHash", 1, block1, 0)
    55  	checkpoint2 := addCheckpoint(t, ctx, checkpointStore, "myOtherHash", "myOtherBlockHash", 2, block2, 0)
    56  
    57  	t.Run("GetAll", func(t *testing.T) {
    58  		expected := []entities.Checkpoint{checkpoint2, checkpoint1}
    59  		pagination := entities.CursorPagination{NewestFirst: true}
    60  		actual, _, err := checkpointStore.GetAll(ctx, pagination)
    61  		require.NoError(t, err)
    62  		assert.Equal(t, expected, actual)
    63  	})
    64  }
    65  
    66  func TestCheckpointsSameHashAndBlock(t *testing.T) {
    67  	ctx := tempTransaction(t)
    68  
    69  	checkpointStore := sqlstore.NewCheckpoints(connectionSource)
    70  	blockStore := sqlstore.NewBlocks(connectionSource)
    71  	block1 := addTestBlock(t, ctx, blockStore)
    72  
    73  	checkpoint1 := addCheckpoint(t, ctx, checkpointStore, "myHash", "myBlockHash", 1, block1, 0)
    74  	checkpoint2 := addCheckpoint(t, ctx, checkpointStore, "myHash", "myBlockHash", 1, block1, 1)
    75  
    76  	t.Run("GetAll", func(t *testing.T) {
    77  		expected := []entities.Checkpoint{checkpoint1, checkpoint2}
    78  		pagination := entities.CursorPagination{NewestFirst: true}
    79  		actual, _, err := checkpointStore.GetAll(ctx, pagination)
    80  		require.NoError(t, err)
    81  		assert.Equal(t, expected, actual)
    82  	})
    83  }
    84  
    85  func TestCheckpointPagination(t *testing.T) {
    86  	t.Run("should return all checkpoints if no pagination is specified", testCheckpointPaginationNoPagination)
    87  	t.Run("should return first page of checkpoints if first is provided", testCheckpointPaginationFirst)
    88  	t.Run("should return last page of checkpoints if last is provided", testCheckpointPaginationLast)
    89  	t.Run("should return specified page of checkpoints if first and after is specified", testCheckpointPaginationFirstAndAfter)
    90  	t.Run("should return specified page of checkpoints if last and before is specified", testCheckpointPaginationLastAndBefore)
    91  
    92  	t.Run("should return all checkpoints if no pagination is specified - newest first", testCheckpointPaginationNoPaginationNewestFirst)
    93  	t.Run("should return first page of checkpoints if first is provided - newest first", testCheckpointPaginationFirstNewestFirst)
    94  	t.Run("should return last page of checkpoints if last is provided - newest first", testCheckpointPaginationLastNewestFirst)
    95  	t.Run("should return specified page of checkpoints if first and after is specified - newest first", testCheckpointPaginationFirstAndAfterNewestFirst)
    96  	t.Run("should return specified page of checkpoints if last and before is specified - newest first", testCheckpointPaginationLastAndBeforeNewestFirst)
    97  }
    98  
    99  func testCheckpointPaginationNoPagination(t *testing.T) {
   100  	ctx := tempTransaction(t)
   101  
   102  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   103  
   104  	pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, false)
   105  	require.NoError(t, err)
   106  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   107  	require.NoError(t, err)
   108  	want := checkpoints
   109  	assert.Equal(t, want, got)
   110  	assert.Equal(t, entities.PageInfo{
   111  		HasNextPage:     false,
   112  		HasPreviousPage: false,
   113  		StartCursor:     checkpoints[0].Cursor().Encode(),
   114  		EndCursor:       checkpoints[9].Cursor().Encode(),
   115  	}, pageInfo)
   116  }
   117  
   118  func testCheckpointPaginationFirst(t *testing.T) {
   119  	ctx := tempTransaction(t)
   120  
   121  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   122  
   123  	first := int32(3)
   124  	pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, false)
   125  	require.NoError(t, err)
   126  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   127  	require.NoError(t, err)
   128  	want := checkpoints[:3]
   129  	assert.Equal(t, want, got)
   130  	assert.Equal(t, entities.PageInfo{
   131  		HasNextPage:     true,
   132  		HasPreviousPage: false,
   133  		StartCursor:     checkpoints[0].Cursor().Encode(),
   134  		EndCursor:       checkpoints[2].Cursor().Encode(),
   135  	}, pageInfo)
   136  }
   137  
   138  func testCheckpointPaginationLast(t *testing.T) {
   139  	ctx := tempTransaction(t)
   140  
   141  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   142  
   143  	last := int32(3)
   144  	pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, false)
   145  	require.NoError(t, err)
   146  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   147  	require.NoError(t, err)
   148  	want := checkpoints[7:]
   149  	assert.Equal(t, want, got)
   150  	assert.Equal(t, entities.PageInfo{
   151  		HasNextPage:     false,
   152  		HasPreviousPage: true,
   153  		StartCursor:     checkpoints[7].Cursor().Encode(),
   154  		EndCursor:       checkpoints[9].Cursor().Encode(),
   155  	}, pageInfo)
   156  }
   157  
   158  func testCheckpointPaginationFirstAndAfter(t *testing.T) {
   159  	ctx := tempTransaction(t)
   160  
   161  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   162  
   163  	first := int32(3)
   164  	after := checkpoints[2].Cursor().Encode()
   165  	pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, false)
   166  	require.NoError(t, err)
   167  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   168  	require.NoError(t, err)
   169  	want := checkpoints[3:6]
   170  	assert.Equal(t, want, got)
   171  	assert.Equal(t, entities.PageInfo{
   172  		HasNextPage:     true,
   173  		HasPreviousPage: true,
   174  		StartCursor:     checkpoints[3].Cursor().Encode(),
   175  		EndCursor:       checkpoints[5].Cursor().Encode(),
   176  	}, pageInfo)
   177  }
   178  
   179  func testCheckpointPaginationLastAndBefore(t *testing.T) {
   180  	ctx := tempTransaction(t)
   181  
   182  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   183  
   184  	last := int32(3)
   185  	before := checkpoints[7].Cursor().Encode()
   186  	pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, false)
   187  	require.NoError(t, err)
   188  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   189  	require.NoError(t, err)
   190  	want := checkpoints[4:7]
   191  	assert.Equal(t, want, got)
   192  	assert.Equal(t, entities.PageInfo{
   193  		HasNextPage:     true,
   194  		HasPreviousPage: true,
   195  		StartCursor:     checkpoints[4].Cursor().Encode(),
   196  		EndCursor:       checkpoints[6].Cursor().Encode(),
   197  	}, pageInfo)
   198  }
   199  
   200  func testCheckpointPaginationNoPaginationNewestFirst(t *testing.T) {
   201  	ctx := tempTransaction(t)
   202  
   203  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   204  	checkpoints = entities.ReverseSlice(checkpoints)
   205  
   206  	pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, true)
   207  	require.NoError(t, err)
   208  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   209  	require.NoError(t, err)
   210  	want := checkpoints
   211  	assert.Equal(t, want, got)
   212  	assert.Equal(t, entities.PageInfo{
   213  		HasNextPage:     false,
   214  		HasPreviousPage: false,
   215  		StartCursor:     checkpoints[0].Cursor().Encode(),
   216  		EndCursor:       checkpoints[9].Cursor().Encode(),
   217  	}, pageInfo)
   218  }
   219  
   220  func testCheckpointPaginationFirstNewestFirst(t *testing.T) {
   221  	ctx := tempTransaction(t)
   222  
   223  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   224  	checkpoints = entities.ReverseSlice(checkpoints)
   225  
   226  	first := int32(3)
   227  	pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, true)
   228  	require.NoError(t, err)
   229  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   230  	require.NoError(t, err)
   231  	want := checkpoints[:3]
   232  	assert.Equal(t, want, got)
   233  	assert.Equal(t, entities.PageInfo{
   234  		HasNextPage:     true,
   235  		HasPreviousPage: false,
   236  		StartCursor:     checkpoints[0].Cursor().Encode(),
   237  		EndCursor:       checkpoints[2].Cursor().Encode(),
   238  	}, pageInfo)
   239  }
   240  
   241  func testCheckpointPaginationLastNewestFirst(t *testing.T) {
   242  	ctx := tempTransaction(t)
   243  
   244  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   245  	checkpoints = entities.ReverseSlice(checkpoints)
   246  
   247  	last := int32(3)
   248  	pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, true)
   249  	require.NoError(t, err)
   250  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   251  	require.NoError(t, err)
   252  	want := checkpoints[7:]
   253  	assert.Equal(t, want, got)
   254  	assert.Equal(t, entities.PageInfo{
   255  		HasNextPage:     false,
   256  		HasPreviousPage: true,
   257  		StartCursor:     checkpoints[7].Cursor().Encode(),
   258  		EndCursor:       checkpoints[9].Cursor().Encode(),
   259  	}, pageInfo)
   260  }
   261  
   262  func testCheckpointPaginationFirstAndAfterNewestFirst(t *testing.T) {
   263  	ctx := tempTransaction(t)
   264  
   265  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   266  	checkpoints = entities.ReverseSlice(checkpoints)
   267  
   268  	first := int32(3)
   269  	after := checkpoints[2].Cursor().Encode()
   270  	pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, true)
   271  	require.NoError(t, err)
   272  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   273  	require.NoError(t, err)
   274  	want := checkpoints[3:6]
   275  	assert.Equal(t, want, got)
   276  	assert.Equal(t, entities.PageInfo{
   277  		HasNextPage:     true,
   278  		HasPreviousPage: true,
   279  		StartCursor:     checkpoints[3].Cursor().Encode(),
   280  		EndCursor:       checkpoints[5].Cursor().Encode(),
   281  	}, pageInfo)
   282  }
   283  
   284  func testCheckpointPaginationLastAndBeforeNewestFirst(t *testing.T) {
   285  	ctx := tempTransaction(t)
   286  
   287  	cs, checkpoints := setupCheckpointPaginationTest(t, ctx)
   288  	checkpoints = entities.ReverseSlice(checkpoints)
   289  
   290  	last := int32(3)
   291  	before := checkpoints[7].Cursor().Encode()
   292  	pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, true)
   293  	require.NoError(t, err)
   294  	got, pageInfo, err := cs.GetAll(ctx, pagination)
   295  	require.NoError(t, err)
   296  	want := checkpoints[4:7]
   297  	assert.Equal(t, want, got)
   298  	assert.Equal(t, entities.PageInfo{
   299  		HasNextPage:     true,
   300  		HasPreviousPage: true,
   301  		StartCursor:     checkpoints[4].Cursor().Encode(),
   302  		EndCursor:       checkpoints[6].Cursor().Encode(),
   303  	}, pageInfo)
   304  }
   305  
   306  func setupCheckpointPaginationTest(t *testing.T, ctx context.Context) (*sqlstore.Checkpoints, []entities.Checkpoint) {
   307  	t.Helper()
   308  	bs := sqlstore.NewBlocks(connectionSource)
   309  	cs := sqlstore.NewCheckpoints(connectionSource)
   310  	blockTime := time.Date(2022, 7, 27, 8, 0, 0, 0, time.Local)
   311  	checkPoints := make([]entities.Checkpoint, 10)
   312  
   313  	for i := 0; i < 10; i++ {
   314  		blockTime = blockTime.Add(time.Minute)
   315  		block := addTestBlockForTime(t, ctx, bs, blockTime)
   316  		hash := int64(i + 1)
   317  		checkPoints[i] = addCheckpoint(t, ctx, cs, fmt.Sprintf("TestHash%02d", hash), fmt.Sprintf("TestBlockHash%02d", hash), hash, block, uint64(i))
   318  	}
   319  
   320  	return cs, checkPoints
   321  }