code.vegaprotocol.io/vega@v0.79.0/datanode/entities/entities_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 entities_test
    17  
    18  import (
    19  	"crypto/sha256"
    20  	"encoding/hex"
    21  	"math/rand"
    22  	"strconv"
    23  	"testing"
    24  	"time"
    25  
    26  	"code.vegaprotocol.io/vega/datanode/entities"
    27  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    28  
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  func generateTxHash() entities.TxHash {
    34  	randomString := strconv.FormatInt(rand.Int63(), 10)
    35  	hash := sha256.Sum256([]byte(randomString))
    36  	return entities.TxHash(hex.EncodeToString(hash[:]))
    37  }
    38  
    39  func TestPageEntities(t *testing.T) {
    40  	t.Run("Number of results is 2 more then the page limit", func(t *testing.T) {
    41  		t.Run("The results are returned in order and we have next and previous when we are moving forward", testPageEntitiesForwardHasNextAndPrevious)
    42  		t.Run("The results are returned in order and we have next and previous when we are moving backward", testPageEntitiesBackwardHasNextAndPrevious)
    43  	})
    44  
    45  	t.Run("Number of results is 1 more than the page limit", func(t *testing.T) {
    46  		t.Run("When moving forward, we have a previous page, but no next page", testPagedEntitiesForwardHasPreviousButNoNext)
    47  		t.Run("When moving backward, we have a next page, but no previous page", testPagedEntitiesBackwardHasNextButNoPrevious)
    48  	})
    49  
    50  	t.Run("Number of results is equal to the page limit", func(t *testing.T) {
    51  		t.Run("When moving forward, we have no previous or next page", testPagedEntitiesForwardNoNextOrPreviousEqualLimit)
    52  		t.Run("When moving backward, we have no previous or next page", testPagedEntitiesBackwardNoNextOrPreviousEqualLimit)
    53  	})
    54  
    55  	t.Run("Number of results is less than the page limit", func(t *testing.T) {
    56  		t.Run("When moving forward, we have no previous or next page", testPagedEntitiesForwardNoNextOrPreviousLessThanLimit)
    57  		t.Run("When moving backward, we have no previous or next page", testPagedEntitiesBackwardNoNextOrPreviousLessThanLimit)
    58  	})
    59  }
    60  
    61  func testPageEntitiesForwardHasNextAndPrevious(t *testing.T) {
    62  	trades := getTradesForward(t, 0, 0) // 0, 0 return all entries
    63  	first := int32(5)
    64  	afterTs := time.Unix(0, 1000000000000).UTC()
    65  	after := entities.NewCursor(entities.TradeCursor{
    66  		SyntheticTime: afterTs,
    67  	}.String()).Encode()
    68  	newestFirst := false
    69  	cursor, err := entities.CursorPaginationFromProto(
    70  		&v2.Pagination{
    71  			First:       &first,
    72  			After:       &after,
    73  			Last:        nil,
    74  			Before:      nil,
    75  			NewestFirst: &newestFirst,
    76  		})
    77  	require.NoError(t, err)
    78  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
    79  
    80  	startCursor := entities.NewCursor(entities.TradeCursor{
    81  		SyntheticTime: time.Unix(0, 1000001000000).UTC(),
    82  	}.String()).Encode()
    83  
    84  	endCursor := entities.NewCursor(entities.TradeCursor{
    85  		SyntheticTime: time.Unix(0, 1000005000000).UTC(),
    86  	}.String()).Encode()
    87  
    88  	wantPaged := trades[1:6]
    89  	wantInfo := entities.PageInfo{
    90  		HasNextPage:     true,
    91  		HasPreviousPage: true,
    92  		StartCursor:     startCursor,
    93  		EndCursor:       endCursor,
    94  	}
    95  	assert.Equal(t, wantPaged, gotPaged)
    96  	assert.Equal(t, wantInfo, gotInfo)
    97  }
    98  
    99  func testPageEntitiesBackwardHasNextAndPrevious(t *testing.T) {
   100  	trades := getTradesBackward(t, 0, 0) // 0, 0 return all entries
   101  	last := int32(5)
   102  	beforeTs := time.Unix(0, 1000006000000).UTC()
   103  	before := entities.NewCursor(entities.TradeCursor{
   104  		SyntheticTime: beforeTs,
   105  	}.String()).Encode()
   106  	newestFirst := false
   107  	cursor, err := entities.CursorPaginationFromProto(
   108  		&v2.Pagination{
   109  			First:       nil,
   110  			After:       nil,
   111  			Last:        &last,
   112  			Before:      &before,
   113  			NewestFirst: &newestFirst,
   114  		})
   115  	require.NoError(t, err)
   116  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   117  
   118  	startCursor := entities.NewCursor(entities.TradeCursor{
   119  		SyntheticTime: time.Unix(0, 1000001000000).UTC(),
   120  	}.String()).Encode()
   121  
   122  	endCursor := entities.NewCursor(entities.TradeCursor{
   123  		SyntheticTime: time.Unix(0, 1000005000000).UTC(),
   124  	}.String()).Encode()
   125  
   126  	wantPaged := getTradesForward(t, 1, 6)
   127  	wantInfo := entities.PageInfo{
   128  		HasNextPage:     true,
   129  		HasPreviousPage: true,
   130  		StartCursor:     startCursor,
   131  		EndCursor:       endCursor,
   132  	}
   133  	assert.Equal(t, wantPaged, gotPaged)
   134  	assert.Equal(t, wantInfo, gotInfo)
   135  }
   136  
   137  func testPagedEntitiesForwardHasPreviousButNoNext(t *testing.T) {
   138  	trades := getTradesForward(t, 1, 0) // 0, 0 return all entries
   139  	first := int32(5)
   140  	afterTs := time.Unix(0, 1000001000000).UTC()
   141  	after := entities.NewCursor(entities.TradeCursor{
   142  		SyntheticTime: afterTs,
   143  	}.String()).Encode()
   144  	newestFirst := false
   145  	cursor, err := entities.CursorPaginationFromProto(
   146  		&v2.Pagination{
   147  			First:       &first,
   148  			After:       &after,
   149  			Last:        nil,
   150  			Before:      nil,
   151  			NewestFirst: &newestFirst,
   152  		})
   153  	require.NoError(t, err)
   154  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   155  
   156  	startCursor := entities.NewCursor(entities.TradeCursor{
   157  		SyntheticTime: time.Unix(0, 1000002000000).UTC(),
   158  	}.String()).Encode()
   159  
   160  	endCursor := entities.NewCursor(entities.TradeCursor{
   161  		SyntheticTime: time.Unix(0, 1000006000000).UTC(),
   162  	}.String()).Encode()
   163  
   164  	wantPaged := trades[1:6]
   165  	wantInfo := entities.PageInfo{
   166  		HasNextPage:     false,
   167  		HasPreviousPage: true,
   168  		StartCursor:     startCursor,
   169  		EndCursor:       endCursor,
   170  	}
   171  	assert.Equal(t, wantPaged, gotPaged)
   172  	assert.Equal(t, wantInfo, gotInfo)
   173  }
   174  
   175  func testPagedEntitiesBackwardHasNextButNoPrevious(t *testing.T) {
   176  	trades := getTradesBackward(t, 1, 0) // 0, 0 return all entries
   177  	last := int32(5)
   178  	beforeTs := time.Unix(0, 1000005000000).UTC()
   179  	before := entities.NewCursor(entities.TradeCursor{
   180  		SyntheticTime: beforeTs,
   181  	}.String()).Encode()
   182  	newestFirst := false
   183  	cursor, err := entities.CursorPaginationFromProto(
   184  		&v2.Pagination{
   185  			First:       nil,
   186  			After:       nil,
   187  			Last:        &last,
   188  			Before:      &before,
   189  			NewestFirst: &newestFirst,
   190  		})
   191  	require.NoError(t, err)
   192  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   193  
   194  	startCursor := entities.NewCursor(entities.TradeCursor{
   195  		SyntheticTime: time.Unix(0, 1000000000000).UTC(),
   196  	}.String()).Encode()
   197  
   198  	endCursor := entities.NewCursor(entities.TradeCursor{
   199  		SyntheticTime: time.Unix(0, 1000004000000).UTC(),
   200  	}.String()).Encode()
   201  
   202  	wantPaged := getTradesForward(t, 0, 5)
   203  	wantInfo := entities.PageInfo{
   204  		HasNextPage:     true,
   205  		HasPreviousPage: false,
   206  		StartCursor:     startCursor,
   207  		EndCursor:       endCursor,
   208  	}
   209  	assert.Equal(t, wantPaged, gotPaged)
   210  	assert.Equal(t, wantInfo, gotInfo)
   211  }
   212  
   213  func testPagedEntitiesForwardNoNextOrPreviousEqualLimit(t *testing.T) {
   214  	trades := getTradesForward(t, 0, 5) // 0, 0 return all entries
   215  	first := int32(5)
   216  	newestFirst := false
   217  	cursor, err := entities.CursorPaginationFromProto(
   218  		&v2.Pagination{
   219  			First:       &first,
   220  			After:       nil,
   221  			Last:        nil,
   222  			Before:      nil,
   223  			NewestFirst: &newestFirst,
   224  		})
   225  	require.NoError(t, err)
   226  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   227  
   228  	startCursor := entities.NewCursor(entities.TradeCursor{
   229  		SyntheticTime: time.Unix(0, 1000000000000).UTC(),
   230  	}.String()).Encode()
   231  
   232  	endCursor := entities.NewCursor(entities.TradeCursor{
   233  		SyntheticTime: time.Unix(0, 1000004000000).UTC(),
   234  	}.String()).Encode()
   235  
   236  	wantPaged := trades
   237  	wantInfo := entities.PageInfo{
   238  		HasNextPage:     false,
   239  		HasPreviousPage: false,
   240  		StartCursor:     startCursor,
   241  		EndCursor:       endCursor,
   242  	}
   243  	assert.Equal(t, wantPaged, gotPaged)
   244  	assert.Equal(t, wantInfo, gotInfo)
   245  }
   246  
   247  func testPagedEntitiesBackwardNoNextOrPreviousEqualLimit(t *testing.T) {
   248  	trades := getTradesBackward(t, 0, 5) // 0, 0 return all entries
   249  	last := int32(5)
   250  	newestFirst := false
   251  	cursor, err := entities.CursorPaginationFromProto(
   252  		&v2.Pagination{
   253  			First:       nil,
   254  			After:       nil,
   255  			Last:        &last,
   256  			Before:      nil,
   257  			NewestFirst: &newestFirst,
   258  		})
   259  	require.NoError(t, err)
   260  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   261  
   262  	startCursor := entities.NewCursor(entities.TradeCursor{
   263  		SyntheticTime: time.Unix(0, 1000002000000).UTC(),
   264  	}.String()).Encode()
   265  
   266  	endCursor := entities.NewCursor(entities.TradeCursor{
   267  		SyntheticTime: time.Unix(0, 1000006000000).UTC(),
   268  	}.String()).Encode()
   269  
   270  	wantPaged := getTradesForward(t, 2, 0)
   271  	wantInfo := entities.PageInfo{
   272  		HasNextPage:     false,
   273  		HasPreviousPage: false,
   274  		StartCursor:     startCursor,
   275  		EndCursor:       endCursor,
   276  	}
   277  	assert.Equal(t, wantPaged, gotPaged)
   278  	assert.Equal(t, wantInfo, gotInfo)
   279  }
   280  
   281  func testPagedEntitiesForwardNoNextOrPreviousLessThanLimit(t *testing.T) {
   282  	trades := getTradesForward(t, 0, 3) // 0, 0 return all entries
   283  	first := int32(5)
   284  	newestFirst := false
   285  	cursor, err := entities.CursorPaginationFromProto(
   286  		&v2.Pagination{
   287  			First:       &first,
   288  			After:       nil,
   289  			Last:        nil,
   290  			Before:      nil,
   291  			NewestFirst: &newestFirst,
   292  		})
   293  	require.NoError(t, err)
   294  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   295  
   296  	startCursor := entities.NewCursor(entities.TradeCursor{
   297  		SyntheticTime: time.Unix(0, 1000000000000).UTC(),
   298  	}.String()).Encode()
   299  
   300  	endCursor := entities.NewCursor(entities.TradeCursor{
   301  		SyntheticTime: time.Unix(0, 1000002000000).UTC(),
   302  	}.String()).Encode()
   303  
   304  	wantPaged := trades
   305  	wantInfo := entities.PageInfo{
   306  		HasNextPage:     false,
   307  		HasPreviousPage: false,
   308  		StartCursor:     startCursor,
   309  		EndCursor:       endCursor,
   310  	}
   311  	assert.Equal(t, wantPaged, gotPaged)
   312  	assert.Equal(t, wantInfo, gotInfo)
   313  }
   314  
   315  func testPagedEntitiesBackwardNoNextOrPreviousLessThanLimit(t *testing.T) {
   316  	trades := getTradesBackward(t, 0, 3) // 0, 0 return all entries
   317  	last := int32(5)
   318  	newestFirst := false
   319  	cursor, err := entities.CursorPaginationFromProto(
   320  		&v2.Pagination{
   321  			First:       nil,
   322  			After:       nil,
   323  			Last:        &last,
   324  			Before:      nil,
   325  			NewestFirst: &newestFirst,
   326  		})
   327  	require.NoError(t, err)
   328  	gotPaged, gotInfo := entities.PageEntities[*v2.TradeEdge](trades, cursor)
   329  
   330  	startCursor := entities.NewCursor(entities.TradeCursor{
   331  		SyntheticTime: time.Unix(0, 1000004000000).UTC(),
   332  	}.String()).Encode()
   333  
   334  	endCursor := entities.NewCursor(entities.TradeCursor{
   335  		SyntheticTime: time.Unix(0, 1000006000000).UTC(),
   336  	}.String()).Encode()
   337  
   338  	wantPaged := getTradesForward(t, 4, 0)
   339  	wantInfo := entities.PageInfo{
   340  		HasNextPage:     false,
   341  		HasPreviousPage: false,
   342  		StartCursor:     startCursor,
   343  		EndCursor:       endCursor,
   344  	}
   345  	assert.Equal(t, wantPaged, gotPaged)
   346  	assert.Equal(t, wantInfo, gotInfo)
   347  }
   348  
   349  func getTradesForward(t *testing.T, start, end int) []entities.Trade {
   350  	t.Helper()
   351  	trades := []entities.Trade{
   352  		{
   353  			SyntheticTime: time.Unix(0, 1000000000000).UTC(),
   354  		},
   355  		{
   356  			SyntheticTime: time.Unix(0, 1000001000000).UTC(),
   357  		},
   358  		{
   359  			SyntheticTime: time.Unix(0, 1000002000000).UTC(),
   360  		},
   361  		{
   362  			SyntheticTime: time.Unix(0, 1000003000000).UTC(),
   363  		},
   364  		{
   365  			SyntheticTime: time.Unix(0, 1000004000000).UTC(),
   366  		},
   367  		{
   368  			SyntheticTime: time.Unix(0, 1000005000000).UTC(),
   369  		},
   370  		{
   371  			SyntheticTime: time.Unix(0, 1000006000000).UTC(),
   372  		},
   373  	}
   374  
   375  	if end == 0 {
   376  		end = len(trades)
   377  	}
   378  
   379  	if end < start {
   380  		end = start
   381  	}
   382  
   383  	return trades[start:end]
   384  }
   385  
   386  func getTradesBackward(t *testing.T, start, end int) []entities.Trade {
   387  	t.Helper()
   388  	trades := []entities.Trade{
   389  		{
   390  			SyntheticTime: time.Unix(0, 1000006000000).UTC(),
   391  		},
   392  		{
   393  			SyntheticTime: time.Unix(0, 1000005000000).UTC(),
   394  		},
   395  		{
   396  			SyntheticTime: time.Unix(0, 1000004000000).UTC(),
   397  		},
   398  		{
   399  			SyntheticTime: time.Unix(0, 1000003000000).UTC(),
   400  		},
   401  		{
   402  			SyntheticTime: time.Unix(0, 1000002000000).UTC(),
   403  		},
   404  		{
   405  			SyntheticTime: time.Unix(0, 1000001000000).UTC(),
   406  		},
   407  		{
   408  			SyntheticTime: time.Unix(0, 1000000000000).UTC(),
   409  		},
   410  	}
   411  
   412  	if end == 0 {
   413  		end = len(trades)
   414  	}
   415  
   416  	if end < start {
   417  		end = start
   418  	}
   419  
   420  	return trades[start:end]
   421  }