code.vegaprotocol.io/vega@v0.79.0/core/teams/helpers_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 teams_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"code.vegaprotocol.io/vega/core/events"
    25  	"code.vegaprotocol.io/vega/core/integration/stubs"
    26  	"code.vegaprotocol.io/vega/core/snapshot"
    27  	"code.vegaprotocol.io/vega/core/stats"
    28  	"code.vegaprotocol.io/vega/core/teams"
    29  	"code.vegaprotocol.io/vega/core/teams/mocks"
    30  	"code.vegaprotocol.io/vega/core/types"
    31  	vgcrypto "code.vegaprotocol.io/vega/libs/crypto"
    32  	"code.vegaprotocol.io/vega/libs/ptr"
    33  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    34  	"code.vegaprotocol.io/vega/logging"
    35  	"code.vegaprotocol.io/vega/paths"
    36  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    37  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    38  
    39  	"github.com/golang/mock/gomock"
    40  	"github.com/stretchr/testify/assert"
    41  	"github.com/stretchr/testify/require"
    42  )
    43  
    44  type testEngine struct {
    45  	engine       *teams.SnapshottedEngine
    46  	broker       *mocks.MockBroker
    47  	timeService  *mocks.MockTimeService
    48  	currentEpoch uint64
    49  }
    50  
    51  func assertEqualTeams(t *testing.T, expected, actual []types.Team) {
    52  	t.Helper()
    53  
    54  	teams.SortByTeamID(expected)
    55  	teams.SortByTeamID(actual)
    56  
    57  	if len(expected) != len(actual) {
    58  		assert.Fail(t, fmt.Sprintf("Expected len of %d but got %d", len(expected), len(actual)))
    59  	}
    60  
    61  	for i := 0; i < len(expected); i++ {
    62  		t.Run(fmt.Sprintf("team #%d", i), func(tt *testing.T) {
    63  			expectedTeam := expected[i]
    64  			actualTeam := actual[i]
    65  			assert.Equal(tt, expectedTeam.ID, actualTeam.ID)
    66  			assert.Equal(tt, expectedTeam.Name, actualTeam.Name)
    67  			assert.Equal(tt, expectedTeam.TeamURL, actualTeam.TeamURL)
    68  			assert.Equal(tt, expectedTeam.AvatarURL, actualTeam.AvatarURL)
    69  			assert.Equal(tt, expectedTeam.CreatedAt.UnixNano(), actualTeam.CreatedAt.UnixNano())
    70  			assert.Equal(tt, expectedTeam.Closed, actualTeam.Closed)
    71  			assert.Equal(tt, expectedTeam.AllowList, actualTeam.AllowList)
    72  			assertEqualMembership(tt, expectedTeam.Referrer, actualTeam.Referrer)
    73  
    74  			if len(expectedTeam.Referees) != len(actualTeam.Referees) {
    75  				assert.Fail(tt, fmt.Sprintf("number of referees in expected and actual results mismatch, expecting %d but got %d", len(expectedTeam.Referees), len(actualTeam.Referees)))
    76  				return
    77  			}
    78  
    79  			for j := 0; j < len(expectedTeam.Referees); j++ {
    80  				tt.Run(fmt.Sprintf("referee #%d", j), func(ttt *testing.T) {
    81  					assertEqualMembership(ttt, expectedTeam.Referees[j], actualTeam.Referees[j])
    82  				})
    83  			}
    84  		})
    85  	}
    86  }
    87  
    88  func assertEqualMembership(t *testing.T, expected, actual *types.Membership) {
    89  	t.Helper()
    90  
    91  	assert.Equal(t, expected.PartyID, actual.PartyID)
    92  	assert.Equal(t, expected.JoinedAt.UnixNano(), actual.JoinedAt.UnixNano())
    93  	assert.Equal(t, expected.StartedAtEpoch, actual.StartedAtEpoch)
    94  }
    95  
    96  func expectTeamCreatedEvent(t *testing.T, engine *testEngine) {
    97  	t.Helper()
    98  
    99  	engine.broker.EXPECT().Send(gomock.Any()).Do(func(evt events.Event) {
   100  		_, ok := evt.(*events.TeamCreated)
   101  		assert.True(t, ok, "Event should be a TeamCreated, but is %T", evt)
   102  	}).Times(1)
   103  }
   104  
   105  func expectTeamUpdatedEvent(t *testing.T, engine *testEngine) {
   106  	t.Helper()
   107  
   108  	engine.broker.EXPECT().Send(gomock.Any()).Do(func(evt events.Event) {
   109  		_, ok := evt.(*events.TeamUpdated)
   110  		assert.True(t, ok, "Event should be a TeamUpdated, but is %T", evt)
   111  	}).Times(1)
   112  }
   113  
   114  func expectRefereeJoinedTeamEvent(t *testing.T, engine *testEngine) {
   115  	t.Helper()
   116  
   117  	engine.broker.EXPECT().Send(gomock.Any()).Do(func(evt events.Event) {
   118  		_, ok := evt.(*events.RefereeJoinedTeam)
   119  		assert.True(t, ok, "Event should be a RefereeJoinedTeam, but is %T", evt)
   120  	}).Times(1)
   121  }
   122  
   123  func expectRefereeSwitchedTeamEvent(t *testing.T, engine *testEngine) {
   124  	t.Helper()
   125  
   126  	engine.broker.EXPECT().Send(gomock.Any()).Do(func(evt events.Event) {
   127  		_, ok := evt.(*events.RefereeSwitchedTeam)
   128  		assert.True(t, ok, "Event should be a RefereeSwitchedTeam, but is %T", evt)
   129  	}).Times(1)
   130  }
   131  
   132  func nextEpoch(t *testing.T, ctx context.Context, te *testEngine, startEpochTime time.Time) {
   133  	t.Helper()
   134  
   135  	te.engine.OnEpoch(ctx, types.Epoch{
   136  		Seq:     te.currentEpoch,
   137  		Action:  vegapb.EpochAction_EPOCH_ACTION_END,
   138  		EndTime: startEpochTime.Add(-1 * time.Second),
   139  	})
   140  
   141  	te.currentEpoch += 1
   142  	te.engine.OnEpoch(ctx, types.Epoch{
   143  		Seq:       te.currentEpoch,
   144  		Action:    vegapb.EpochAction_EPOCH_ACTION_START,
   145  		StartTime: startEpochTime,
   146  	})
   147  }
   148  
   149  func newSnapshotEngine(t *testing.T, vegaPath paths.Paths, now time.Time, engine *teams.SnapshottedEngine) *snapshot.Engine {
   150  	t.Helper()
   151  
   152  	log := logging.NewTestLogger()
   153  	timeService := stubs.NewTimeStub()
   154  	timeService.SetTime(now)
   155  	statsData := stats.New(log, stats.NewDefaultConfig())
   156  	config := snapshot.DefaultConfig()
   157  
   158  	snapshotEngine, err := snapshot.NewEngine(vegaPath, config, log, timeService, statsData.Blockchain)
   159  	require.NoError(t, err)
   160  
   161  	snapshotEngine.AddProviders(engine)
   162  
   163  	return snapshotEngine
   164  }
   165  
   166  func newEngine(t *testing.T) *testEngine {
   167  	t.Helper()
   168  
   169  	ctrl := gomock.NewController(t)
   170  
   171  	broker := mocks.NewMockBroker(ctrl)
   172  	timeService := mocks.NewMockTimeService(ctrl)
   173  
   174  	engine := teams.NewSnapshottedEngine(broker, timeService)
   175  
   176  	engine.OnEpochRestore(context.Background(), types.Epoch{
   177  		Seq:    10,
   178  		Action: vegapb.EpochAction_EPOCH_ACTION_START,
   179  	})
   180  
   181  	return &testEngine{
   182  		engine:       engine,
   183  		broker:       broker,
   184  		timeService:  timeService,
   185  		currentEpoch: 10,
   186  	}
   187  }
   188  
   189  func newTeamID(t *testing.T) types.TeamID {
   190  	t.Helper()
   191  
   192  	return types.TeamID(vgcrypto.RandomHash())
   193  }
   194  
   195  func newPartyID(t *testing.T) types.PartyID {
   196  	t.Helper()
   197  
   198  	return types.PartyID(vgrand.RandomStr(5))
   199  }
   200  
   201  func newTeam(t *testing.T, ctx context.Context, te *testEngine) (types.TeamID, types.PartyID, string) {
   202  	t.Helper()
   203  
   204  	teamID := newTeamID(t)
   205  	referrer := newPartyID(t)
   206  	teamName := vgrand.RandomStr(5)
   207  
   208  	expectTeamCreatedEvent(t, te)
   209  
   210  	err := te.engine.CreateTeam(ctx, referrer, teamID, createTeamCmd(t, teamName, "", ""))
   211  	require.NoError(t, err)
   212  	require.NotEmpty(t, teamID)
   213  	require.True(t, te.engine.IsTeamMember(referrer))
   214  
   215  	return teamID, referrer, teamName
   216  }
   217  
   218  func newTeamWithCmd(t *testing.T, ctx context.Context, te *testEngine, cmd *commandspb.CreateReferralSet_Team) (types.TeamID, types.PartyID) {
   219  	t.Helper()
   220  
   221  	teamID := newTeamID(t)
   222  	referrer := newPartyID(t)
   223  
   224  	expectTeamCreatedEvent(t, te)
   225  
   226  	err := te.engine.CreateTeam(ctx, referrer, teamID, cmd)
   227  	require.NoError(t, err)
   228  	require.NotEmpty(t, teamID)
   229  	require.True(t, te.engine.IsTeamMember(referrer))
   230  
   231  	return teamID, referrer
   232  }
   233  
   234  func createTeamCmd(t *testing.T, name, teamURL, avatarURL string) *commandspb.CreateReferralSet_Team {
   235  	t.Helper()
   236  
   237  	return &commandspb.CreateReferralSet_Team{
   238  		Name:      name,
   239  		TeamUrl:   ptr.From(teamURL),
   240  		AvatarUrl: ptr.From(avatarURL),
   241  	}
   242  }
   243  
   244  func createTeamWithAllowListCmd(t *testing.T, name, teamURL, avatarURL string, closed bool, allowList []string) *commandspb.CreateReferralSet_Team {
   245  	t.Helper()
   246  
   247  	return &commandspb.CreateReferralSet_Team{
   248  		Name:      name,
   249  		TeamUrl:   ptr.From(teamURL),
   250  		AvatarUrl: ptr.From(avatarURL),
   251  		Closed:    closed,
   252  		AllowList: allowList,
   253  	}
   254  }
   255  
   256  func updateTeamCmd(t *testing.T, name, teamURL, avatarURL string, closed bool, allowList []string) *commandspb.UpdateReferralSet_Team {
   257  	t.Helper()
   258  
   259  	return &commandspb.UpdateReferralSet_Team{
   260  		Name:      ptr.From(name),
   261  		TeamUrl:   ptr.From(teamURL),
   262  		AvatarUrl: ptr.From(avatarURL),
   263  		Closed:    ptr.From(closed),
   264  		AllowList: allowList,
   265  	}
   266  }
   267  
   268  func joinTeamCmd(t *testing.T, teamID types.TeamID) *commandspb.JoinTeam {
   269  	t.Helper()
   270  
   271  	return &commandspb.JoinTeam{
   272  		Id: string(teamID),
   273  	}
   274  }