github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/services/wireguard/service/service_test.go (about)

     1  /*
     2   * Copyright (C) 2018 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  	"net"
    22  	"sync"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  
    28  	"github.com/mysteriumnetwork/node/core/ip"
    29  	"github.com/mysteriumnetwork/node/core/policy/localcopy"
    30  	"github.com/mysteriumnetwork/node/core/service"
    31  	"github.com/mysteriumnetwork/node/core/service/servicestate"
    32  	"github.com/mysteriumnetwork/node/dns"
    33  	"github.com/mysteriumnetwork/node/identity"
    34  	"github.com/mysteriumnetwork/node/market"
    35  	"github.com/mysteriumnetwork/node/nat"
    36  	wg "github.com/mysteriumnetwork/node/services/wireguard"
    37  	"github.com/mysteriumnetwork/node/services/wireguard/wgcfg"
    38  )
    39  
    40  var (
    41  	pubIP   = "127.0.0.1"
    42  	outIP   = "127.0.0.1"
    43  	country = "LT"
    44  )
    45  
    46  var connectionEndpointStub = &mockConnectionEndpoint{}
    47  
    48  func Test_Manager_Stop(t *testing.T) {
    49  	manager := newManagerStub(pubIP, outIP, country)
    50  
    51  	service := service.NewInstance(
    52  		identity.FromAddress("0x1"),
    53  		"",
    54  		nil,
    55  		market.ServiceProposal{},
    56  		servicestate.Running,
    57  		nil,
    58  		localcopy.NewRepository(),
    59  		nil,
    60  	)
    61  
    62  	go func() {
    63  		err := manager.Serve(service)
    64  		assert.NoError(t, err)
    65  	}()
    66  
    67  	waitABit()
    68  	err := manager.Stop()
    69  	assert.NoError(t, err)
    70  }
    71  
    72  func Test_Manager_Stop_Datarace(t *testing.T) {
    73  	manager := newManagerStub(pubIP, outIP, country)
    74  
    75  	service := service.NewInstance(
    76  		identity.FromAddress("0x1"),
    77  		"",
    78  		nil,
    79  		market.ServiceProposal{},
    80  		servicestate.Running,
    81  		nil,
    82  		localcopy.NewRepository(),
    83  		nil,
    84  	)
    85  	manager.sessionCleanup = make(map[string]func())
    86  
    87  	destroyClosure := func(sessionID string) func() {
    88  		return func() {
    89  			manager.sessionCleanupMu.Lock()
    90  			defer manager.sessionCleanupMu.Unlock()
    91  
    92  			_, ok := manager.sessionCleanup[sessionID]
    93  			if !ok {
    94  				return
    95  			}
    96  			delete(manager.sessionCleanup, sessionID)
    97  		}
    98  	}
    99  
   100  	var wg sync.WaitGroup
   101  
   102  	wg.Add(2)
   103  	go func() {
   104  		defer wg.Done()
   105  		err := manager.Serve(service)
   106  		assert.NoError(t, err)
   107  	}()
   108  
   109  	// normally the ProvideConfig() sets a callback, but in unit test we have to do it ourselves
   110  	manager.sessionCleanupMu.Lock()
   111  	manager.sessionCleanup["1"] = destroyClosure("1")
   112  	manager.sessionCleanupMu.Unlock()
   113  
   114  	waitABit()
   115  	go func() {
   116  		defer wg.Done()
   117  		err := manager.Stop()
   118  		assert.NoError(t, err)
   119  	}()
   120  	wg.Wait()
   121  }
   122  
   123  func Test_Manager_ProviderConfig_FailsWhenSessionConfigIsInvalid(t *testing.T) {
   124  	manager := newManagerStub(pubIP, outIP, country)
   125  
   126  	params, err := manager.ProvideConfig("", nil, nil)
   127  
   128  	assert.Nil(t, params)
   129  	assert.Error(t, err)
   130  }
   131  
   132  // usually time.Sleep call gives a chance for other goroutines to kick in important when testing async code
   133  func waitABit() {
   134  	time.Sleep(10 * time.Millisecond)
   135  }
   136  
   137  type mockConnectionEndpoint struct{}
   138  
   139  func (mce *mockConnectionEndpoint) StartConsumerMode(config wgcfg.DeviceConfig) error { return nil }
   140  func (mce *mockConnectionEndpoint) ReconfigureConsumerMode(config wgcfg.DeviceConfig) error {
   141  	return nil
   142  }
   143  
   144  func (mce *mockConnectionEndpoint) StartProviderMode(ip string, config wgcfg.DeviceConfig) error {
   145  	return nil
   146  }
   147  func (mce *mockConnectionEndpoint) InterfaceName() string                { return "mce0" }
   148  func (mce *mockConnectionEndpoint) Stop() error                          { return nil }
   149  func (mce *mockConnectionEndpoint) Config() (wg.ServiceConfig, error)    { return wg.ServiceConfig{}, nil }
   150  func (mce *mockConnectionEndpoint) AddPeer(_ string, _ wgcfg.Peer) error { return nil }
   151  func (mce *mockConnectionEndpoint) RemovePeer(_ string) error            { return nil }
   152  func (mce *mockConnectionEndpoint) ConfigureRoutes(_ net.IP) error       { return nil }
   153  func (mce *mockConnectionEndpoint) PeerStats() (wgcfg.Stats, error) {
   154  	return wgcfg.Stats{LastHandshake: time.Now()}, nil
   155  }
   156  
   157  func newManagerStub(pub, out, country string) *Manager {
   158  	dnsHandler, _ := dns.ResolveViaSystem()
   159  
   160  	return &Manager{
   161  		done:       make(chan struct{}),
   162  		ipResolver: ip.NewResolverMock("1.2.3.4"),
   163  		natService: &serviceFake{},
   164  		connEndpointFactory: func() (wg.ConnectionEndpoint, error) {
   165  			return connectionEndpointStub, nil
   166  		},
   167  		dnsProxy: dns.NewProxy("", 0, dnsHandler),
   168  	}
   169  }
   170  
   171  type serviceFake struct{}
   172  
   173  func (service *serviceFake) Setup(nat.Options) (rules []interface{}, err error) {
   174  	return nil, nil
   175  }
   176  func (service *serviceFake) Del([]interface{}) error { return nil }
   177  func (service *serviceFake) Enable() error           { return nil }
   178  func (service *serviceFake) Disable() error          { return nil }