github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/service/manager_test.go (about)

     1  /*
     2   * Copyright (C) 2019 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package service
    19  
    20  import (
    21  	"errors"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/mysteriumnetwork/node/core/policy/localcopy"
    26  	"github.com/mysteriumnetwork/node/core/policy/requested"
    27  
    28  	"github.com/mysteriumnetwork/node/core/location/locationstate"
    29  	"github.com/mysteriumnetwork/node/core/service/servicestate"
    30  	"github.com/mysteriumnetwork/node/identity"
    31  	"github.com/mysteriumnetwork/node/market"
    32  	"github.com/mysteriumnetwork/node/mocks"
    33  	"github.com/mysteriumnetwork/node/p2p"
    34  	"github.com/mysteriumnetwork/node/requests"
    35  	"github.com/mysteriumnetwork/node/utils/netutil"
    36  	"github.com/stretchr/testify/assert"
    37  )
    38  
    39  var (
    40  	serviceType        = "the-very-awesome-test-service-type"
    41  	mockPolicyOracle   = localcopy.NewOracle(requests.NewHTTPClient("0.0.0.0", requests.DefaultTimeout), "http://policy.localhost/", 1*time.Minute, true)
    42  	mockPolicyProvider = requested.NewRequestedProvider(requests.NewHTTPClient("0.0.0.0", requests.DefaultTimeout), "http://policy.localhost/")
    43  )
    44  
    45  func init() {
    46  	netutil.LogNetworkStats = func() {}
    47  }
    48  
    49  func TestManager_StartRemovesServiceFromPoolIfServiceCrashes(t *testing.T) {
    50  	registry := NewRegistry()
    51  	mockCopy := *serviceMock
    52  	mockCopy.onStartReturnError = errors.New("some error")
    53  	registry.Register(serviceType, func(options Options) (Service, error) {
    54  		return &mockCopy, nil
    55  	})
    56  
    57  	discovery := mockDiscovery{}
    58  	discoveryFactory := MockDiscoveryFactoryFunc(&discovery)
    59  	manager := NewManager(
    60  		registry,
    61  		discoveryFactory,
    62  		mocks.NewEventBus(),
    63  		mockPolicyOracle,
    64  		mockPolicyProvider,
    65  		&mockP2PListener{}, nil, nil, mockLocationResolver{},
    66  	)
    67  	_, err := manager.Start(identity.FromAddress(proposalMock.ProviderID), serviceType, nil, struct{}{})
    68  	assert.Nil(t, err)
    69  
    70  	discovery.Wait()
    71  	assert.Len(t, manager.servicePool.List(), 0)
    72  }
    73  
    74  func TestManager_StartDoesNotCrashIfStoppedByUser(t *testing.T) {
    75  	registry := NewRegistry()
    76  	mockCopy := *serviceMock
    77  	mockCopy.mockProcess = make(chan struct{})
    78  	registry.Register(serviceType, func(options Options) (Service, error) {
    79  		return &mockCopy, nil
    80  	})
    81  
    82  	discovery := mockDiscovery{}
    83  	discoveryFactory := MockDiscoveryFactoryFunc(&discovery)
    84  	manager := NewManager(
    85  		registry,
    86  		discoveryFactory,
    87  		mocks.NewEventBus(),
    88  		mockPolicyOracle,
    89  		mockPolicyProvider,
    90  		&mockP2PListener{}, nil, nil,
    91  		mockLocationResolver{},
    92  	)
    93  	id, err := manager.Start(identity.FromAddress(proposalMock.ProviderID), serviceType, nil, struct{}{})
    94  	assert.Nil(t, err)
    95  	err = manager.Stop(id)
    96  	assert.Nil(t, err)
    97  	discovery.Wait()
    98  	assert.Len(t, manager.servicePool.List(), 0)
    99  }
   100  
   101  func TestManager_StopSendsEvent_SucceedsAndPublishesEvent(t *testing.T) {
   102  	registry := NewRegistry()
   103  	mockCopy := *serviceMock
   104  	mockCopy.mockProcess = make(chan struct{})
   105  	registry.Register(serviceType, func(options Options) (Service, error) {
   106  		return &mockCopy, nil
   107  	})
   108  
   109  	discovery := mockDiscovery{}
   110  	discoveryFactory := MockDiscoveryFactoryFunc(&discovery)
   111  	eventBus := &mockPublisher{}
   112  	manager := NewManager(
   113  		registry,
   114  		discoveryFactory,
   115  		eventBus,
   116  		mockPolicyOracle,
   117  		mockPolicyProvider,
   118  		&mockP2PListener{}, nil, nil,
   119  		mockLocationResolver{},
   120  	)
   121  
   122  	id, err := manager.Start(identity.FromAddress(proposalMock.ProviderID), serviceType, nil, struct{}{})
   123  	assert.NoError(t, err)
   124  
   125  	services := manager.servicePool.List()
   126  
   127  	var serviceID ID
   128  	for k := range services {
   129  		serviceID = services[k].ID
   130  	}
   131  
   132  	err = manager.Stop(id)
   133  	assert.NoError(t, err)
   134  
   135  	time.Sleep(time.Millisecond * 30)
   136  
   137  	eventBus.lock.Lock()
   138  	defer eventBus.lock.Unlock()
   139  
   140  	assert.Equal(t, servicestate.AppTopicServiceStatus, eventBus.publishedTopic)
   141  
   142  	var matchFound bool
   143  	expectedPayload := servicestate.AppEventServiceStatus{ID: string(serviceID), ProviderID: "", Type: "", Status: "NotRunning"}
   144  	for i := range eventBus.publishedData {
   145  		e, ok := eventBus.publishedData[i].(servicestate.AppEventServiceStatus)
   146  		if !ok {
   147  			continue
   148  		}
   149  		if e.Status == expectedPayload.Status && e.ID == expectedPayload.ID {
   150  			matchFound = true
   151  			break
   152  		}
   153  	}
   154  	assert.True(t, matchFound)
   155  }
   156  
   157  type mockP2PListener struct {
   158  }
   159  
   160  func (m mockP2PListener) GetContact() market.Contact {
   161  	return market.Contact{}
   162  }
   163  
   164  func (m mockP2PListener) Listen(_ identity.Identity, serviceType string, channelHandler func(ch p2p.Channel)) (func(), error) {
   165  	return func() {}, nil
   166  }
   167  
   168  type mockLocationResolver struct {
   169  }
   170  
   171  func (m mockLocationResolver) DetectLocation() (locationstate.Location, error) {
   172  	return locationstate.Location{}, nil
   173  }