code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/game_scores_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  	"sort"
    21  	"testing"
    22  	"time"
    23  
    24  	"code.vegaprotocol.io/vega/datanode/entities"
    25  	"code.vegaprotocol.io/vega/datanode/sqlstore"
    26  	"code.vegaprotocol.io/vega/libs/num"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  type gameScoresTestStore struct {
    33  	gs *sqlstore.GameScores
    34  }
    35  
    36  func newGameScoresTestStore(t *testing.T) *gameScoresTestStore {
    37  	t.Helper()
    38  	return &gameScoresTestStore{
    39  		gs: sqlstore.NewGameScores(connectionSource),
    40  	}
    41  }
    42  
    43  func TestInsertPartyScores(t *testing.T) {
    44  	ctx := tempTransaction(t)
    45  	store := newGameScoresTestStore(t)
    46  	now := time.Now()
    47  	gps := entities.GamePartyScore{
    48  		GameID:         "FFFF",
    49  		EpochID:        1,
    50  		PartyID:        "EEEE",
    51  		Score:          num.DecimalOne(),
    52  		StakingBalance: num.DecimalTwo(),
    53  		OpenVolume:     num.DecimalZero(),
    54  		TotalFeesPaid:  num.DecimalFromInt64(4),
    55  		IsEligible:     true,
    56  		VegaTime:       now,
    57  	}
    58  
    59  	t.Run("can insert successfully", func(t *testing.T) {
    60  		assert.NoError(t, store.gs.AddPartyScore(ctx, gps))
    61  	})
    62  
    63  	team := entities.TeamID("AAAA")
    64  	gps.GameID = "BBBB"
    65  	gps.TeamID = &team
    66  	t.Run("can insert successfully with team", func(t *testing.T) {
    67  		assert.NoError(t, store.gs.AddPartyScore(ctx, gps))
    68  	})
    69  
    70  	rank := uint64(2)
    71  	gps.PartyID = "BBBB"
    72  	gps.Rank = &rank
    73  	t.Run("can insert successfully with rank", func(t *testing.T) {
    74  		assert.NoError(t, store.gs.AddPartyScore(ctx, gps))
    75  	})
    76  }
    77  
    78  func TestInsertTeamScores(t *testing.T) {
    79  	ctx := tempTransaction(t)
    80  	store := newGameScoresTestStore(t)
    81  	now := time.Now()
    82  	gts := entities.GameTeamScore{
    83  		GameID:   "FFFF",
    84  		EpochID:  1,
    85  		TeamID:   "EEEE",
    86  		Score:    num.DecimalOne(),
    87  		VegaTime: now,
    88  	}
    89  
    90  	t.Run("can insert successfully", func(t *testing.T) {
    91  		require.NoError(t, store.gs.AddTeamScore(ctx, gts))
    92  	})
    93  }
    94  
    95  func prepopoulatePartyScores(t *testing.T, ctx context.Context, gs *gameScoresTestStore, now time.Time) []entities.GamePartyScore {
    96  	t.Helper()
    97  	team1 := entities.TeamID("AAAA")
    98  	team2 := entities.TeamID("BBBB")
    99  	team3 := entities.TeamID("CCCC")
   100  	gps := []entities.GamePartyScore{
   101  		{
   102  			GameID:         "EEEE",
   103  			EpochID:        1,
   104  			PartyID:        "FFFE",
   105  			TeamID:         &team3,
   106  			Score:          num.DecimalFromFloat(0.1),
   107  			StakingBalance: num.DecimalFromInt64(1),
   108  			OpenVolume:     num.DecimalFromInt64(2),
   109  			TotalFeesPaid:  num.DecimalFromInt64(3),
   110  			IsEligible:     true,
   111  			VegaTime:       now,
   112  		},
   113  		{
   114  			GameID:         "FFFF",
   115  			EpochID:        1,
   116  			PartyID:        "FFFE",
   117  			TeamID:         &team1,
   118  			Score:          num.DecimalFromFloat(0.1),
   119  			StakingBalance: num.DecimalFromInt64(1),
   120  			OpenVolume:     num.DecimalFromInt64(2),
   121  			TotalFeesPaid:  num.DecimalFromInt64(3),
   122  			IsEligible:     true,
   123  			VegaTime:       now,
   124  		},
   125  		{
   126  			GameID:         "EEFF",
   127  			EpochID:        1,
   128  			PartyID:        "FFFD",
   129  			TeamID:         &team2,
   130  			Score:          num.DecimalFromFloat(0.2),
   131  			StakingBalance: num.DecimalFromInt64(11),
   132  			OpenVolume:     num.DecimalFromInt64(22),
   133  			TotalFeesPaid:  num.DecimalFromInt64(33),
   134  			IsEligible:     true,
   135  			VegaTime:       now,
   136  		},
   137  		{
   138  			GameID:         "FFFF",
   139  			EpochID:        1,
   140  			PartyID:        "FFFD",
   141  			Score:          num.DecimalFromFloat(0.2),
   142  			StakingBalance: num.DecimalFromInt64(111),
   143  			OpenVolume:     num.DecimalFromInt64(222),
   144  			TotalFeesPaid:  num.DecimalFromInt64(333),
   145  			IsEligible:     true,
   146  			VegaTime:       now,
   147  		},
   148  		{
   149  			GameID:         "FFFF",
   150  			EpochID:        1,
   151  			PartyID:        "FFFC",
   152  			TeamID:         &team3,
   153  			Score:          num.DecimalFromFloat(0.3),
   154  			StakingBalance: num.DecimalFromInt64(1111),
   155  			OpenVolume:     num.DecimalFromInt64(2222),
   156  			TotalFeesPaid:  num.DecimalFromInt64(3333),
   157  			IsEligible:     true,
   158  			VegaTime:       now,
   159  		},
   160  		{
   161  			GameID:         "FFFF",
   162  			EpochID:        1,
   163  			PartyID:        "FFFB",
   164  			TeamID:         &team3,
   165  			Score:          num.DecimalFromFloat(0.4),
   166  			StakingBalance: num.DecimalFromInt64(11111),
   167  			OpenVolume:     num.DecimalFromInt64(22222),
   168  			TotalFeesPaid:  num.DecimalFromInt64(33333),
   169  			IsEligible:     true,
   170  			VegaTime:       now,
   171  		},
   172  		{
   173  			GameID:         "FFFF",
   174  			EpochID:        1,
   175  			PartyID:        "FFFA",
   176  			Score:          num.DecimalFromFloat(0.5),
   177  			StakingBalance: num.DecimalTwo(),
   178  			OpenVolume:     num.DecimalZero(),
   179  			TotalFeesPaid:  num.DecimalFromInt64(4),
   180  			IsEligible:     true,
   181  			VegaTime:       now,
   182  		},
   183  		{
   184  			GameID:         "FFFF",
   185  			EpochID:        2,
   186  			PartyID:        "FFFA",
   187  			Score:          num.DecimalFromFloat(0.8),
   188  			StakingBalance: num.DecimalFromInt64(6),
   189  			OpenVolume:     num.DecimalFromInt64(3),
   190  			TotalFeesPaid:  num.DecimalFromInt64(1),
   191  			IsEligible:     true,
   192  			VegaTime:       now.Add(1 * time.Second),
   193  		},
   194  		{
   195  			GameID:         "FFFF",
   196  			EpochID:        2,
   197  			PartyID:        "FFFA",
   198  			Score:          num.DecimalFromFloat(0.7),
   199  			StakingBalance: num.DecimalFromInt64(9),
   200  			OpenVolume:     num.DecimalFromInt64(8),
   201  			TotalFeesPaid:  num.DecimalFromInt64(7),
   202  			IsEligible:     true,
   203  			VegaTime:       now.Add(2 * time.Second),
   204  		},
   205  	}
   206  	for _, gps1 := range gps {
   207  		require.NoError(t, gs.gs.AddPartyScore(ctx, gps1))
   208  	}
   209  	sort.Slice(gps, func(i, j int) bool {
   210  		if gps[i].GameID == gps[j].GameID {
   211  			return gps[i].PartyID > gps[j].PartyID
   212  		}
   213  		return gps[i].GameID > gps[j].GameID
   214  	})
   215  
   216  	return gps
   217  }
   218  
   219  func TestListPartyScoresNoFilters(t *testing.T) {
   220  	ctx := tempTransaction(t)
   221  	store := newGameScoresTestStore(t)
   222  	now := time.Now()
   223  	pagination, _ := entities.NewCursorPagination(nil, nil, nil, nil, true)
   224  	partyScores := prepopoulatePartyScores(t, ctx, store, now)
   225  	scores, _, err := store.gs.ListPartyScores(ctx, nil, nil, nil, nil, nil, pagination)
   226  	require.NoError(t, err)
   227  	// as we're not filtering by epochs we're getting the current scores so that's equal to all the ones from epoch 1 (which are all distinct)
   228  	require.Equal(t, len(partyScores)-2, len(scores))
   229  
   230  	// now insert a fresh score for an existing party for the same game
   231  	now = now.Add(time.Hour)
   232  	partyScores[0].VegaTime = now
   233  	partyScores[0].Score = num.DecimalE()
   234  	require.NoError(t, store.gs.AddPartyScore(ctx, partyScores[0]))
   235  	require.Equal(t, len(partyScores)-2, len(scores))
   236  }
   237  
   238  func TestListPartyScoresPartyFilters(t *testing.T) {
   239  	ctx := tempTransaction(t)
   240  	store := newGameScoresTestStore(t)
   241  	now := time.Now()
   242  	pagination, _ := entities.NewCursorPagination(nil, nil, nil, nil, true)
   243  	prepopoulatePartyScores(t, ctx, store, now)
   244  	scores, _, err := store.gs.ListPartyScores(ctx, nil, []entities.PartyID{"FFFD"}, nil, nil, nil, pagination)
   245  	require.NoError(t, err)
   246  	require.Equal(t, 2, len(scores))
   247  
   248  	scores, _, err = store.gs.ListPartyScores(ctx, nil, []entities.PartyID{"FFFD", "FFFE"}, nil, nil, nil, pagination)
   249  	require.NoError(t, err)
   250  	require.Equal(t, 4, len(scores))
   251  }
   252  
   253  func TestListPartyScoresGameFilters(t *testing.T) {
   254  	ctx := tempTransaction(t)
   255  	store := newGameScoresTestStore(t)
   256  	now := time.Now()
   257  	pagination, _ := entities.NewCursorPagination(nil, nil, nil, nil, true)
   258  	ps := prepopoulatePartyScores(t, ctx, store, now)
   259  	scores, _, err := store.gs.ListPartyScores(ctx, []entities.GameID{"EEFF"}, nil, nil, nil, nil, pagination)
   260  	require.NoError(t, err)
   261  	require.Equal(t, 1, len(scores))
   262  
   263  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF", "EEEE"}, nil, nil, nil, nil, pagination)
   264  	require.NoError(t, err)
   265  	require.Equal(t, len(ps)-3, len(scores))
   266  }
   267  
   268  func TestListPartyScoresTeamFilters(t *testing.T) {
   269  	ctx := tempTransaction(t)
   270  	store := newGameScoresTestStore(t)
   271  	now := time.Now()
   272  	pagination, _ := entities.NewCursorPagination(nil, nil, nil, nil, true)
   273  	prepopoulatePartyScores(t, ctx, store, now)
   274  	scores, _, err := store.gs.ListPartyScores(ctx, nil, nil, []entities.TeamID{"AAAA"}, nil, nil, pagination)
   275  	require.NoError(t, err)
   276  	require.Equal(t, 1, len(scores))
   277  	scores, _, err = store.gs.ListPartyScores(ctx, nil, nil, []entities.TeamID{"AAAA", "BBBB"}, nil, nil, pagination)
   278  	require.NoError(t, err)
   279  	require.Equal(t, 2, len(scores))
   280  }
   281  
   282  func TestListPartyScoresAllFilters(t *testing.T) {
   283  	ctx := tempTransaction(t)
   284  	store := newGameScoresTestStore(t)
   285  	now := time.Now()
   286  	pagination, _ := entities.NewCursorPagination(nil, nil, nil, nil, true)
   287  	prepopoulatePartyScores(t, ctx, store, now)
   288  
   289  	// all filters populated
   290  	scores, _, err := store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFB"}, []entities.TeamID{"CCCC"}, nil, nil, pagination)
   291  	require.NoError(t, err)
   292  	require.Equal(t, 1, len(scores))
   293  	require.Equal(t, num.DecimalFromFloat(0.4), scores[0].Score)
   294  	require.Equal(t, num.DecimalFromInt64(11111), scores[0].StakingBalance)
   295  	require.Equal(t, num.DecimalFromInt64(22222), scores[0].OpenVolume)
   296  	require.Equal(t, num.DecimalFromInt64(33333), scores[0].TotalFeesPaid)
   297  }
   298  
   299  func TestListPartyScoresEpochFilter(t *testing.T) {
   300  	ctx := tempTransaction(t)
   301  	store := newGameScoresTestStore(t)
   302  	now := time.Now()
   303  	pagination, _ := entities.NewCursorPagination(nil, nil, nil, nil, true)
   304  	prepopoulatePartyScores(t, ctx, store, now)
   305  
   306  	// all filters populated
   307  	from := uint64(1)
   308  	to := uint64(2)
   309  	// provide to and from
   310  	scores, _, err := store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, &from, &to, pagination)
   311  	require.NoError(t, err)
   312  	require.Equal(t, 2, len(scores))
   313  	require.Equal(t, num.DecimalFromFloat(0.5), scores[0].Score)
   314  	require.Equal(t, num.DecimalFromInt64(2), scores[0].StakingBalance)
   315  	require.Equal(t, num.DecimalFromInt64(0), scores[0].OpenVolume)
   316  	require.Equal(t, num.DecimalFromInt64(4), scores[0].TotalFeesPaid)
   317  	require.Equal(t, num.DecimalFromFloat(0.7), scores[1].Score)
   318  	require.Equal(t, num.DecimalFromInt64(9), scores[1].StakingBalance)
   319  	require.Equal(t, num.DecimalFromInt64(8), scores[1].OpenVolume)
   320  	require.Equal(t, num.DecimalFromInt64(7), scores[1].TotalFeesPaid)
   321  
   322  	// do not provide from, expect the same result as we should get basically all epochs
   323  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, nil, &to, pagination)
   324  	require.NoError(t, err)
   325  	require.Equal(t, 2, len(scores))
   326  	require.Equal(t, num.DecimalFromFloat(0.5), scores[0].Score)
   327  	require.Equal(t, num.DecimalFromInt64(2), scores[0].StakingBalance)
   328  	require.Equal(t, num.DecimalFromInt64(0), scores[0].OpenVolume)
   329  	require.Equal(t, num.DecimalFromInt64(4), scores[0].TotalFeesPaid)
   330  	require.Equal(t, num.DecimalFromFloat(0.7), scores[1].Score)
   331  	require.Equal(t, num.DecimalFromInt64(9), scores[1].StakingBalance)
   332  	require.Equal(t, num.DecimalFromInt64(8), scores[1].OpenVolume)
   333  	require.Equal(t, num.DecimalFromInt64(7), scores[1].TotalFeesPaid)
   334  
   335  	// do not provide to, expect the same result as we should get basically all epochs
   336  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, &from, nil, pagination)
   337  	require.NoError(t, err)
   338  	require.Equal(t, 2, len(scores))
   339  	require.Equal(t, num.DecimalFromFloat(0.5), scores[0].Score)
   340  	require.Equal(t, num.DecimalFromInt64(2), scores[0].StakingBalance)
   341  	require.Equal(t, num.DecimalFromInt64(0), scores[0].OpenVolume)
   342  	require.Equal(t, num.DecimalFromInt64(4), scores[0].TotalFeesPaid)
   343  	require.Equal(t, num.DecimalFromFloat(0.7), scores[1].Score)
   344  	require.Equal(t, num.DecimalFromInt64(9), scores[1].StakingBalance)
   345  	require.Equal(t, num.DecimalFromInt64(8), scores[1].OpenVolume)
   346  	require.Equal(t, num.DecimalFromInt64(7), scores[1].TotalFeesPaid)
   347  
   348  	// set from to the second (and last) epoch
   349  	from = 2
   350  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, &from, nil, pagination)
   351  	require.NoError(t, err)
   352  	require.Equal(t, 1, len(scores))
   353  	require.Equal(t, num.DecimalFromFloat(0.7), scores[0].Score)
   354  	require.Equal(t, num.DecimalFromInt64(9), scores[0].StakingBalance)
   355  	require.Equal(t, num.DecimalFromInt64(8), scores[0].OpenVolume)
   356  	require.Equal(t, num.DecimalFromInt64(7), scores[0].TotalFeesPaid)
   357  
   358  	// set to to 1 so we get only the first epoch
   359  	to = 1
   360  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, nil, &to, pagination)
   361  	require.NoError(t, err)
   362  	require.Equal(t, 1, len(scores))
   363  	require.Equal(t, num.DecimalFromFloat(0.5), scores[0].Score)
   364  	require.Equal(t, num.DecimalFromInt64(2), scores[0].StakingBalance)
   365  	require.Equal(t, num.DecimalFromInt64(0), scores[0].OpenVolume)
   366  	require.Equal(t, num.DecimalFromInt64(4), scores[0].TotalFeesPaid)
   367  
   368  	// now set both to and from to 1
   369  	to = 1
   370  	from = 1
   371  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, &from, &to, pagination)
   372  	require.NoError(t, err)
   373  	require.Equal(t, 1, len(scores))
   374  	require.Equal(t, num.DecimalFromFloat(0.5), scores[0].Score)
   375  	require.Equal(t, num.DecimalFromInt64(2), scores[0].StakingBalance)
   376  	require.Equal(t, num.DecimalFromInt64(0), scores[0].OpenVolume)
   377  	require.Equal(t, num.DecimalFromInt64(4), scores[0].TotalFeesPaid)
   378  
   379  	// and to 2
   380  	to = 2
   381  	from = 2
   382  	scores, _, err = store.gs.ListPartyScores(ctx, []entities.GameID{"FFFF"}, []entities.PartyID{"FFFA"}, nil, &from, &to, pagination)
   383  	require.NoError(t, err)
   384  	require.Equal(t, num.DecimalFromFloat(0.7), scores[0].Score)
   385  	require.Equal(t, num.DecimalFromInt64(9), scores[0].StakingBalance)
   386  	require.Equal(t, num.DecimalFromInt64(8), scores[0].OpenVolume)
   387  	require.Equal(t, num.DecimalFromInt64(7), scores[0].TotalFeesPaid)
   388  }