code.vegaprotocol.io/vega@v0.79.0/datanode/service/position_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 service_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  
    23  	"code.vegaprotocol.io/vega/datanode/entities"
    24  	"code.vegaprotocol.io/vega/datanode/service"
    25  	"code.vegaprotocol.io/vega/datanode/service/mocks"
    26  	"code.vegaprotocol.io/vega/logging"
    27  
    28  	"github.com/golang/mock/gomock"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  var (
    33  	market1ID     = entities.MarketID("aa")
    34  	market2ID     = entities.MarketID("bb")
    35  	party1ID      = entities.PartyID("cc")
    36  	party2ID      = entities.PartyID("dd")
    37  	testPosition1 = entities.Position{MarketID: market1ID, PartyID: party1ID, OpenVolume: 1}
    38  	testPosition2 = entities.Position{MarketID: market2ID, PartyID: party2ID, OpenVolume: 2}
    39  	testPosition3 = entities.Position{MarketID: market1ID, PartyID: party1ID, OpenVolume: 10}
    40  )
    41  
    42  func TestPositionAdd(t *testing.T) {
    43  	ctx := context.Background()
    44  	ctrl := gomock.NewController(t)
    45  
    46  	// Make a new store and add a position to it
    47  	store := mocks.NewMockPositionStore(ctrl)
    48  	store.EXPECT().Add(ctx, gomock.Any()).Return(nil).Times(3)
    49  
    50  	svc := service.NewPosition(store, logging.NewTestLogger())
    51  	svc.Add(ctx, testPosition1)
    52  	svc.Add(ctx, testPosition2)
    53  	svc.Add(ctx, testPosition3)
    54  
    55  	// We don't expect a call to the store's GetByMarketAndParty() method as it should be cached
    56  	// testPosition3 has the same market/party as testPosition1 so should replace it
    57  	fetched, err := svc.GetByMarketAndParty(ctx, market1ID.String(), party1ID.String())
    58  	assert.NoError(t, err)
    59  	assert.Equal(t, testPosition3, fetched)
    60  
    61  	fetched, err = svc.GetByMarketAndParty(ctx, market2ID.String(), party2ID.String())
    62  	assert.NoError(t, err)
    63  	assert.Equal(t, testPosition2, fetched)
    64  }
    65  
    66  func TestCache(t *testing.T) {
    67  	ctx := context.Background()
    68  	ctrl := gomock.NewController(t)
    69  
    70  	// Simulate store with one position in it
    71  	store := mocks.NewMockPositionStore(ctrl)
    72  	store.EXPECT().GetByMarketAndParty(ctx, market1ID.String(), party1ID.String()).Return(testPosition1, nil)
    73  
    74  	svc := service.NewPosition(store, logging.NewTestLogger())
    75  
    76  	// First time should call through to the store
    77  	fetched, err := svc.GetByMarketAndParty(ctx, market1ID.String(), party1ID.String())
    78  	assert.NoError(t, err)
    79  	assert.Equal(t, testPosition1, fetched)
    80  
    81  	// Second time should use cache (we only EXPECT one call above)
    82  	fetched, err = svc.GetByMarketAndParty(ctx, market1ID.String(), party1ID.String())
    83  	assert.NoError(t, err)
    84  	assert.Equal(t, testPosition1, fetched)
    85  }
    86  
    87  func TestCacheError(t *testing.T) {
    88  	ctx := context.Background()
    89  	ctrl := gomock.NewController(t)
    90  	notFoundErr := fmt.Errorf("nothing here i'm afraid")
    91  
    92  	// Simulate store with no positions in it
    93  	store := mocks.NewMockPositionStore(ctrl)
    94  	store.EXPECT().GetByMarketAndParty(ctx, market1ID.String(), party1ID.String()).Times(2).Return(
    95  		entities.Position{},
    96  		notFoundErr,
    97  	)
    98  
    99  	svc := service.NewPosition(store, logging.NewTestLogger())
   100  
   101  	// First time should call through to the store and return error
   102  	fetched, err := svc.GetByMarketAndParty(ctx, market1ID.String(), party1ID.String())
   103  	assert.ErrorIs(t, notFoundErr, err)
   104  	assert.Equal(t, entities.Position{}, fetched)
   105  
   106  	// Second time should use cache but still get same error
   107  	fetched, err = svc.GetByMarketAndParty(ctx, market1ID.String(), party1ID.String())
   108  	assert.ErrorIs(t, notFoundErr, err)
   109  	assert.Equal(t, entities.Position{}, fetched)
   110  }