code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/teams_helper_for_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  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"code.vegaprotocol.io/vega/datanode/entities"
    26  	"code.vegaprotocol.io/vega/datanode/sqlstore"
    27  
    28  	"github.com/stretchr/testify/require"
    29  	"golang.org/x/exp/maps"
    30  	"golang.org/x/exp/slices"
    31  )
    32  
    33  func setupTeamsTest(t *testing.T) (*sqlstore.Blocks, *sqlstore.Teams, *sqlstore.Parties) {
    34  	t.Helper()
    35  
    36  	bs := sqlstore.NewBlocks(connectionSource)
    37  	ts := sqlstore.NewTeams(connectionSource)
    38  	ps := sqlstore.NewParties(connectionSource)
    39  
    40  	return bs, ts, ps
    41  }
    42  
    43  func setupTeams(t *testing.T, ctx context.Context, bs *sqlstore.Blocks, ps *sqlstore.Parties, ts *sqlstore.Teams) ([]entities.Team, []entities.TeamMember) {
    44  	t.Helper()
    45  
    46  	teams := make([]entities.Team, 0, 10)
    47  	teamsHistory := []entities.TeamMember{}
    48  
    49  	for i := 0; i < 10; i++ {
    50  		block := addTestBlock(t, ctx, bs)
    51  		referrer := addTestParty(t, ctx, ps, block)
    52  		team := entities.Team{
    53  			ID:             entities.TeamID(GenerateID()),
    54  			Referrer:       referrer.ID,
    55  			Name:           fmt.Sprintf("Test Team %02d", i+1),
    56  			TotalMembers:   1, // The referrer.
    57  			CreatedAt:      block.VegaTime,
    58  			CreatedAtEpoch: 1,
    59  			VegaTime:       block.VegaTime,
    60  		}
    61  		err := ts.AddTeam(ctx, &team)
    62  		require.NoError(t, err)
    63  		teams = append(teams, team)
    64  		teamsHistory = append(teamsHistory, entities.TeamMember{
    65  			TeamID:        team.ID,
    66  			PartyID:       referrer.ID,
    67  			JoinedAtEpoch: 1,
    68  			JoinedAt:      block.VegaTime,
    69  			VegaTime:      block.VegaTime,
    70  		})
    71  
    72  		time.Sleep(10 * time.Millisecond)
    73  	}
    74  
    75  	for iTeam, team := range teams {
    76  		block := addTestBlock(t, ctx, bs)
    77  		for i := 0; i < 10; i++ {
    78  			referee := addTestParty(t, ctx, ps, block)
    79  			teamReferee := entities.TeamMember{
    80  				TeamID:        team.ID,
    81  				PartyID:       referee.ID,
    82  				JoinedAt:      block.VegaTime,
    83  				JoinedAtEpoch: 2,
    84  				VegaTime:      block.VegaTime,
    85  			}
    86  			err := ts.RefereeJoinedTeam(ctx, &teamReferee)
    87  			require.NoError(t, err)
    88  			teamsHistory = append(teamsHistory, teamReferee)
    89  
    90  			team.TotalMembers += 1
    91  			teams[iTeam] = team
    92  		}
    93  		time.Sleep(10 * time.Millisecond)
    94  	}
    95  
    96  	switchingReferee := teamsHistory[len(teams)].PartyID
    97  
    98  	for i, toTeam := range teams {
    99  		if i == 0 {
   100  			continue
   101  		}
   102  
   103  		fromTeam := teams[i-1]
   104  
   105  		block := addTestBlock(t, ctx, bs)
   106  		switchTeam := entities.RefereeTeamSwitch{
   107  			FromTeamID:      fromTeam.ID,
   108  			ToTeamID:        toTeam.ID,
   109  			PartyID:         switchingReferee,
   110  			SwitchedAtEpoch: uint64(3 + i),
   111  			SwitchedAt:      block.VegaTime,
   112  			VegaTime:        block.VegaTime,
   113  		}
   114  
   115  		require.NoError(t, ts.RefereeSwitchedTeam(ctx, &switchTeam))
   116  
   117  		teamsHistory = append(teamsHistory, entities.TeamMember{
   118  			TeamID:        toTeam.ID,
   119  			PartyID:       switchingReferee,
   120  			JoinedAtEpoch: uint64(3 + i),
   121  			JoinedAt:      block.VegaTime,
   122  			VegaTime:      block.VegaTime,
   123  		})
   124  
   125  		fromTeam.TotalMembers -= 1
   126  		teams[i-1] = fromTeam
   127  
   128  		toTeam.TotalMembers += 1
   129  		teams[i] = toTeam
   130  
   131  		time.Sleep(10 * time.Millisecond)
   132  	}
   133  
   134  	block := addTestBlock(t, ctx, bs)
   135  	for i, team := range teams {
   136  		if i%2 != 0 {
   137  			continue
   138  		}
   139  
   140  		teamDup := team
   141  		teamDup.Closed = true
   142  		teamDup.AllowList = []string{GenerateID(), GenerateID()}
   143  		teams[i] = teamDup
   144  
   145  		require.NoError(t, ts.UpdateTeam(ctx, &entities.TeamUpdated{
   146  			ID:        teamDup.ID,
   147  			Name:      teamDup.Name,
   148  			Closed:    teamDup.Closed,
   149  			AllowList: teamDup.AllowList,
   150  			VegaTime:  block.VegaTime,
   151  		}))
   152  	}
   153  
   154  	return teams, teamsHistory
   155  }
   156  
   157  func historyForReferee(teamsHistory []entities.TeamMember, party entities.PartyID) []entities.TeamMemberHistory {
   158  	var refereeHistory []entities.TeamMemberHistory
   159  
   160  	for _, referee := range teamsHistory {
   161  		if referee.PartyID == party {
   162  			refereeHistory = append(refereeHistory, entities.TeamMemberHistory{
   163  				TeamID:        referee.TeamID,
   164  				JoinedAt:      referee.JoinedAt,
   165  				JoinedAtEpoch: referee.JoinedAtEpoch,
   166  			})
   167  		}
   168  	}
   169  	slices.SortStableFunc(refereeHistory, func(a, b entities.TeamMemberHistory) int {
   170  		return compareUint64(a.JoinedAtEpoch, b.JoinedAtEpoch)
   171  	})
   172  
   173  	return refereeHistory
   174  }
   175  
   176  func currentRefereesForTeam(teamsHistory []entities.TeamMember, teamID entities.TeamID) []entities.TeamMember {
   177  	currentReferees := currentReferees(teamsHistory)
   178  
   179  	currentTeamReferees := []entities.TeamMember{}
   180  	for _, referee := range currentReferees {
   181  		if referee.TeamID == teamID {
   182  			currentTeamReferees = append(currentTeamReferees, referee)
   183  		}
   184  	}
   185  
   186  	slices.SortStableFunc(currentTeamReferees, func(a, b entities.TeamMember) int {
   187  		return strings.Compare(string(a.PartyID), string(b.PartyID))
   188  	})
   189  
   190  	return currentTeamReferees
   191  }
   192  
   193  func currentReferees(teamsHistory []entities.TeamMember) []entities.TeamMember {
   194  	currentReferees := map[entities.PartyID]entities.TeamMember{}
   195  
   196  	for _, teamMember := range teamsHistory {
   197  		// teamMember.JoinedAtEpoch != 1 is a ugly hack to exclude the referrer.
   198  		if teamMember.JoinedAtEpoch == 1 {
   199  			continue
   200  		}
   201  
   202  		previousMembership, ok := currentReferees[teamMember.PartyID]
   203  		if ok {
   204  			if previousMembership.JoinedAtEpoch < teamMember.JoinedAtEpoch {
   205  				currentReferees[teamMember.PartyID] = teamMember
   206  			}
   207  		} else {
   208  			currentReferees[teamMember.PartyID] = teamMember
   209  		}
   210  	}
   211  
   212  	return maps.Values(currentReferees)
   213  }