code.vegaprotocol.io/vega@v0.79.0/wallet/service/service_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  	"io"
    21  	"net/http"
    22  	"net/http/httptest"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	"code.vegaprotocol.io/vega/wallet/api/mocks"
    28  	apimocks "code.vegaprotocol.io/vega/wallet/api/mocks"
    29  	"code.vegaprotocol.io/vega/wallet/network"
    30  	"code.vegaprotocol.io/vega/wallet/service"
    31  	v1 "code.vegaprotocol.io/vega/wallet/service/v1"
    32  	v1mocks "code.vegaprotocol.io/vega/wallet/service/v1/mocks"
    33  	v2 "code.vegaprotocol.io/vega/wallet/service/v2"
    34  	"code.vegaprotocol.io/vega/wallet/service/v2/connections"
    35  	v2connectionsmocks "code.vegaprotocol.io/vega/wallet/service/v2/connections/mocks"
    36  	v2mocks "code.vegaprotocol.io/vega/wallet/service/v2/mocks"
    37  	"code.vegaprotocol.io/vega/wallet/wallet"
    38  
    39  	"github.com/golang/mock/gomock"
    40  	"go.uber.org/zap"
    41  )
    42  
    43  type testService struct {
    44  	*service.Service
    45  
    46  	ctrl              *gomock.Controller
    47  	handler           *v1mocks.MockWalletHandler
    48  	nodeForward       *v1mocks.MockNodeForward
    49  	consentRequestsCh chan v1.ConsentRequest
    50  	auth              *v1mocks.MockAuth
    51  
    52  	clientAPI *v2mocks.MockClientAPI
    53  
    54  	spam         *mocks.MockSpamHandler
    55  	timeService  *v2connectionsmocks.MockTimeService
    56  	walletStore  *v2connectionsmocks.MockWalletStore
    57  	tokenStore   *v2connectionsmocks.MockTokenStore
    58  	sessionStore *v2connectionsmocks.MockSessionStore
    59  	interactor   *apimocks.MockInteractor
    60  }
    61  
    62  func (s *testService) serveHTTP(t *testing.T, req *http.Request) (int, http.Header, []byte) {
    63  	t.Helper()
    64  	w := httptest.NewRecorder()
    65  
    66  	s.ServeHTTP(w, req)
    67  
    68  	resp := w.Result() //nolint:bodyclose
    69  	defer func() {
    70  		if err := w.Result().Body.Close(); err != nil {
    71  			t.Logf("couldn't close response body: %v", err)
    72  		}
    73  	}()
    74  
    75  	body, err := io.ReadAll(resp.Body)
    76  	if err != nil {
    77  		t.Fatalf("couldn't read body: %v", err)
    78  	}
    79  
    80  	return resp.StatusCode, resp.Header, body
    81  }
    82  
    83  func getTestServiceV1(t *testing.T, consentPolicy string) *testService {
    84  	t.Helper()
    85  
    86  	net := &network.Network{}
    87  	serviceCfg := service.DefaultConfig()
    88  
    89  	ctrl := gomock.NewController(t)
    90  
    91  	handler := v1mocks.NewMockWalletHandler(ctrl)
    92  	auth := v1mocks.NewMockAuth(ctrl)
    93  	nodeForward := v1mocks.NewMockNodeForward(ctrl)
    94  	spam := mocks.NewMockSpamHandler(ctrl)
    95  
    96  	consentRequestsCh := make(chan v1.ConsentRequest, 1)
    97  	sentTxs := make(chan v1.SentTransaction, 1)
    98  
    99  	ctx, cancelFn := context.WithCancel(context.Background())
   100  
   101  	var policy v1.Policy
   102  	switch consentPolicy {
   103  	case "automatic":
   104  		policy = v1.NewAutomaticConsentPolicy()
   105  	case "manual":
   106  		policy = v1.NewExplicitConsentPolicy(ctx, consentRequestsCh, sentTxs)
   107  	default:
   108  		t.Fatalf("unknown consent policy: %s", consentPolicy)
   109  	}
   110  
   111  	apiV1 := v1.NewAPI(zap.NewNop(), handler, auth, nodeForward, policy, net, spam)
   112  
   113  	s := service.NewService(zap.NewNop(), serviceCfg, apiV1, nil)
   114  
   115  	t.Cleanup(func() {
   116  		if err := s.Stop(context.Background()); err != nil {
   117  			t.Log("The service couldn't stop properly")
   118  		}
   119  		cancelFn()
   120  		close(consentRequestsCh)
   121  		close(sentTxs)
   122  	})
   123  
   124  	return &testService{
   125  		Service: s,
   126  		ctrl:    ctrl,
   127  
   128  		// V1
   129  		handler:           handler,
   130  		auth:              auth,
   131  		nodeForward:       nodeForward,
   132  		consentRequestsCh: consentRequestsCh,
   133  		spam:              spam,
   134  	}
   135  }
   136  
   137  type longLivingTokenSetupForTest struct {
   138  	tokenDescription connections.TokenDescription
   139  	wallet           wallet.Wallet
   140  }
   141  
   142  func getTestServiceV2(t *testing.T, tokenSetups ...longLivingTokenSetupForTest) *testService {
   143  	t.Helper()
   144  
   145  	serviceCfg := service.DefaultConfig()
   146  
   147  	ctrl := gomock.NewController(t)
   148  
   149  	clientAPI := v2mocks.NewMockClientAPI(ctrl)
   150  	spam := mocks.NewMockSpamHandler(ctrl)
   151  	timeService := v2connectionsmocks.NewMockTimeService(ctrl)
   152  	walletStore := v2connectionsmocks.NewMockWalletStore(ctrl)
   153  	tokenStore := v2connectionsmocks.NewMockTokenStore(ctrl)
   154  	sessionStore := v2connectionsmocks.NewMockSessionStore(ctrl)
   155  	interactor := apimocks.NewMockInteractor(ctrl)
   156  
   157  	if len(tokenSetups) > 0 {
   158  		tokenSummaries := make([]connections.TokenSummary, 0, len(tokenSetups))
   159  		for _, tokenSetup := range tokenSetups {
   160  			tokenSummaries = append(tokenSummaries, connections.TokenSummary{
   161  				Description:    tokenSetup.tokenDescription.Description,
   162  				Token:          tokenSetup.tokenDescription.Token,
   163  				CreationDate:   tokenSetup.tokenDescription.CreationDate,
   164  				ExpirationDate: tokenSetup.tokenDescription.ExpirationDate,
   165  			})
   166  			tokenStore.EXPECT().DescribeToken(tokenSetup.tokenDescription.Token).AnyTimes().Return(tokenSetup.tokenDescription, nil)
   167  			walletStore.EXPECT().UnlockWallet(gomock.Any(), tokenSetup.tokenDescription.Wallet.Name, tokenSetup.tokenDescription.Wallet.Passphrase).Times(1).Return(nil)
   168  			walletStore.EXPECT().GetWallet(gomock.Any(), tokenSetup.tokenDescription.Wallet.Name).Times(1).Return(tokenSetup.wallet, nil)
   169  		}
   170  		tokenStore.EXPECT().ListTokens().AnyTimes().Return(tokenSummaries, nil)
   171  	} else {
   172  		tokenStore.EXPECT().ListTokens().Times(1).Return(nil, nil)
   173  	}
   174  
   175  	sessionStore.EXPECT().ListSessions(gomock.Any()).Times(1).Return(nil, nil)
   176  	timeService.EXPECT().Now().AnyTimes().Return(time.Now())
   177  	walletStore.EXPECT().OnUpdate(gomock.Any()).Times(1)
   178  	tokenStore.EXPECT().OnUpdate(gomock.Any()).Times(1)
   179  
   180  	connectionsManager, err := connections.NewManager(timeService, walletStore, tokenStore, sessionStore, interactor)
   181  	if err != nil {
   182  		t.Fatalf("could not instantiate the connection manager for tests: %v", err)
   183  	}
   184  
   185  	apiV2 := v2.NewAPI(zap.NewNop(), clientAPI, connectionsManager)
   186  
   187  	s := service.NewService(zap.NewNop(), serviceCfg, nil, apiV2)
   188  
   189  	t.Cleanup(func() {
   190  		if err := s.Stop(context.Background()); err != nil {
   191  			t.Log("The service couldn't stop properly")
   192  		}
   193  		connectionsManager.EndAllSessionConnections()
   194  	})
   195  
   196  	return &testService{
   197  		Service: s,
   198  		ctrl:    ctrl,
   199  
   200  		clientAPI:    clientAPI,
   201  		timeService:  timeService,
   202  		walletStore:  walletStore,
   203  		tokenStore:   tokenStore,
   204  		sessionStore: sessionStore,
   205  		interactor:   interactor,
   206  		spam:         spam,
   207  	}
   208  }
   209  
   210  func buildRequest(t *testing.T, method, path, payload string, headers map[string]string) *http.Request {
   211  	t.Helper()
   212  
   213  	ctx, cancelFn := context.WithTimeout(context.Background(), testRequestTimeout)
   214  	t.Cleanup(func() {
   215  		cancelFn()
   216  	})
   217  
   218  	req, _ := http.NewRequestWithContext(ctx, method, path, strings.NewReader(payload))
   219  	for k, v := range headers {
   220  		req.Header.Set(k, v)
   221  	}
   222  	return req
   223  }