code.vegaprotocol.io/vega@v0.79.0/wallet/network/store/v1/file_store_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 v1_test
    17  
    18  import (
    19  	"os"
    20  	"path/filepath"
    21  	"testing"
    22  
    23  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    24  	vgtest "code.vegaprotocol.io/vega/libs/test"
    25  	"code.vegaprotocol.io/vega/paths"
    26  	"code.vegaprotocol.io/vega/wallet/api"
    27  	"code.vegaprotocol.io/vega/wallet/network"
    28  	v1 "code.vegaprotocol.io/vega/wallet/network/store/v1"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func TestFileStoreV1(t *testing.T) {
    35  	t.Run("New store succeeds", testNewStoreSucceeds)
    36  	t.Run("Saving already existing network succeeds", testFileStoreV1SaveAlreadyExistingNetworkSucceeds)
    37  	t.Run("Saving network succeeds", testFileStoreV1SaveNetworkSucceeds)
    38  	t.Run("Saving network with bad name fails", testFileStoreV1SaveNetworkWithBadNameFails)
    39  	t.Run("Verifying non-existing network fails", testFileStoreV1VerifyingNonExistingNetworkFails)
    40  	t.Run("Verifying existing network succeeds", testFileStoreV1VerifyingExistingNetworkSucceeds)
    41  	t.Run("Getting non-existing network fails", testFileStoreV1GetNonExistingNetworkFails)
    42  	t.Run("Getting existing network succeeds", testFileStoreV1GetExistingNetworkSucceeds)
    43  	t.Run("Getting network path succeeds", testFileStoreV1GetNetworkPathSucceeds)
    44  	t.Run("Getting networks path succeeds", testFileStoreV1GetNetworksPathSucceeds)
    45  	t.Run("Listing networks succeeds", testFileStoreV1ListingNetworksSucceeds)
    46  	t.Run("Deleting network succeeds", testFileStoreV1DeleteNetworkSucceeds)
    47  	t.Run("Renaming network succeeds", testFileStoreV1RenamingNetworkSucceeds)
    48  	t.Run("Renaming non-existing network fails", testFileStoreV1RenamingNonExistingNetworkFails)
    49  	t.Run("Renaming network with invalid name fails", testFileStoreV1RenamingNetworkWithInvalidNameFails)
    50  }
    51  
    52  func testNewStoreSucceeds(t *testing.T) {
    53  	vegaHome := newVegaHome(t)
    54  
    55  	s, err := v1.InitialiseStore(vegaHome)
    56  
    57  	require.NoError(t, err)
    58  	assert.NotNil(t, s)
    59  	vgtest.AssertDirAccess(t, networksHome(t, vegaHome))
    60  }
    61  
    62  func testFileStoreV1SaveAlreadyExistingNetworkSucceeds(t *testing.T) {
    63  	vegaHome := newVegaHome(t)
    64  
    65  	// given
    66  	s := initialiseFromPath(t, vegaHome)
    67  	net := &network.Network{
    68  		Name: "test",
    69  	}
    70  
    71  	// when
    72  	err := s.SaveNetwork(net)
    73  
    74  	// then
    75  	require.NoError(t, err)
    76  
    77  	// when
    78  	err = s.SaveNetwork(net)
    79  
    80  	// then
    81  	require.NoError(t, err)
    82  }
    83  
    84  func testFileStoreV1SaveNetworkSucceeds(t *testing.T) {
    85  	vegaHome := newVegaHome(t)
    86  
    87  	// given
    88  	s := initialiseFromPath(t, vegaHome)
    89  	net := &network.Network{
    90  		Name: vgrand.RandomStr(10),
    91  	}
    92  
    93  	// when
    94  	err := s.SaveNetwork(net)
    95  
    96  	// then
    97  	require.NoError(t, err)
    98  	vgtest.AssertFileAccess(t, networkPath(t, vegaHome, net.Name))
    99  
   100  	// confirm that the network name is not saved in the file
   101  	netpath := networkPath(t, vegaHome, net.Name)
   102  	b, err := os.ReadFile(netpath)
   103  	assert.NoError(t, err)
   104  	assert.NotContains(t, string(b), net.Name)
   105  
   106  	// when
   107  	returnedNet, err := s.GetNetwork(net.Name)
   108  
   109  	// then
   110  	require.NoError(t, err)
   111  	assert.Equal(t, net, returnedNet)
   112  	assert.Equal(t, net.Name, returnedNet.Name)
   113  }
   114  
   115  func testFileStoreV1SaveNetworkWithBadNameFails(t *testing.T) {
   116  	vegaHome := newVegaHome(t)
   117  
   118  	// given
   119  	s := initialiseFromPath(t, vegaHome)
   120  
   121  	tcs := []struct {
   122  		name        string
   123  		network     string
   124  		expectedErr error
   125  	}{
   126  		{
   127  			name:        "when empty",
   128  			network:     "",
   129  			expectedErr: v1.ErrNetworkNameCannotBeEmpty,
   130  		}, {
   131  			name:        "starting with `.`",
   132  			network:     "." + vgrand.RandomStr(3),
   133  			expectedErr: v1.ErrNetworkNameCannotStartWithDot,
   134  		}, {
   135  			name:        "with `/`",
   136  			network:     "\\" + vgrand.RandomStr(3) + "/" + vgrand.RandomStr(3),
   137  			expectedErr: v1.ErrNetworkNameCannotContainSlash,
   138  		},
   139  	}
   140  
   141  	for _, tc := range tcs {
   142  		t.Run(tc.name, func(tt *testing.T) {
   143  			net := &network.Network{
   144  				Name: tc.network,
   145  			}
   146  
   147  			// when
   148  			err := s.SaveNetwork(net)
   149  
   150  			// then
   151  			require.ErrorIs(tt, err, tc.expectedErr)
   152  		})
   153  	}
   154  }
   155  
   156  func testFileStoreV1VerifyingNonExistingNetworkFails(t *testing.T) {
   157  	vegaHome := newVegaHome(t)
   158  
   159  	// given
   160  	s := initialiseFromPath(t, vegaHome)
   161  
   162  	// when
   163  	exists, err := s.NetworkExists("test")
   164  
   165  	// then
   166  	assert.NoError(t, err)
   167  	assert.False(t, exists)
   168  }
   169  
   170  func testFileStoreV1VerifyingExistingNetworkSucceeds(t *testing.T) {
   171  	vegaHome := newVegaHome(t)
   172  
   173  	// given
   174  	s := initialiseFromPath(t, vegaHome)
   175  	net := &network.Network{
   176  		Name: "test",
   177  	}
   178  
   179  	// when
   180  	err := s.SaveNetwork(net)
   181  
   182  	// then
   183  	require.NoError(t, err)
   184  	vgtest.AssertFileAccess(t, networkPath(t, vegaHome, net.Name))
   185  
   186  	// when
   187  	exists, err := s.NetworkExists("test")
   188  
   189  	// then
   190  	require.NoError(t, err)
   191  	assert.True(t, exists)
   192  }
   193  
   194  func testFileStoreV1GetNonExistingNetworkFails(t *testing.T) {
   195  	vegaHome := newVegaHome(t)
   196  
   197  	// given
   198  	s := initialiseFromPath(t, vegaHome)
   199  
   200  	// when
   201  	keys, err := s.GetNetwork("test")
   202  
   203  	// then
   204  	assert.Error(t, err)
   205  	assert.Nil(t, keys)
   206  }
   207  
   208  func testFileStoreV1GetExistingNetworkSucceeds(t *testing.T) {
   209  	vegaHome := newVegaHome(t)
   210  
   211  	// given
   212  	s := initialiseFromPath(t, vegaHome)
   213  	net := &network.Network{
   214  		Name: "testnet2",
   215  		Metadata: []network.Metadata{
   216  			{
   217  				Key:   "network",
   218  				Value: "testnet",
   219  			}, {
   220  				Key:   "description",
   221  				Value: "Some network",
   222  			},
   223  		},
   224  		API: network.APIConfig{
   225  			GRPC: network.HostConfig{
   226  				Hosts: []string{
   227  					vgrand.RandomStr(10),
   228  					vgrand.RandomStr(10),
   229  					vgrand.RandomStr(10),
   230  				},
   231  			},
   232  			REST: network.HostConfig{
   233  				Hosts: []string{
   234  					vgrand.RandomStr(10),
   235  					vgrand.RandomStr(10),
   236  				},
   237  			},
   238  			GraphQL: network.HostConfig{
   239  				Hosts: []string{
   240  					vgrand.RandomStr(10),
   241  					vgrand.RandomStr(10),
   242  					vgrand.RandomStr(10),
   243  					vgrand.RandomStr(10),
   244  				},
   245  			},
   246  		},
   247  		Apps: network.AppsConfig{
   248  			Console:    vgrand.RandomStr(10),
   249  			Governance: vgrand.RandomStr(10),
   250  			Explorer:   vgrand.RandomStr(10),
   251  		},
   252  	}
   253  
   254  	// when
   255  	err := s.SaveNetwork(net)
   256  
   257  	// then
   258  	require.NoError(t, err)
   259  	vgtest.AssertFileAccess(t, networkPath(t, vegaHome, net.Name))
   260  
   261  	// when
   262  	returnedNet, err := s.GetNetwork("testnet2")
   263  
   264  	// then
   265  	require.NoError(t, err)
   266  	assert.Equal(t, net, returnedNet)
   267  }
   268  
   269  func testFileStoreV1GetNetworkPathSucceeds(t *testing.T) {
   270  	vegaHome := newVegaHome(t)
   271  
   272  	// given
   273  	s := initialiseFromPath(t, vegaHome)
   274  
   275  	// when
   276  	returnedPath := s.GetNetworkPath("test")
   277  
   278  	// then
   279  	assert.Equal(t, networkPath(t, vegaHome, "test"), returnedPath)
   280  }
   281  
   282  func testFileStoreV1GetNetworksPathSucceeds(t *testing.T) {
   283  	vegaHome := newVegaHome(t)
   284  
   285  	// given
   286  	s := initialiseFromPath(t, vegaHome)
   287  
   288  	// when
   289  	returnedPath := s.GetNetworksPath()
   290  
   291  	// then
   292  	assert.Equal(t, networksHome(t, vegaHome), returnedPath)
   293  }
   294  
   295  func testFileStoreV1ListingNetworksSucceeds(t *testing.T) {
   296  	vegaHome := newVegaHome(t)
   297  
   298  	// given
   299  	s := initialiseFromPath(t, vegaHome)
   300  	net := &network.Network{
   301  		// we use "toml" as name on purpose since we want to verify it's not
   302  		// stripped by the ListNetwork() function.
   303  		Name: "toml",
   304  	}
   305  
   306  	// when
   307  	err := s.SaveNetwork(net)
   308  
   309  	// then
   310  	require.NoError(t, err)
   311  	vgtest.AssertFileAccess(t, networkPath(t, vegaHome, net.Name))
   312  
   313  	// when
   314  	nets, err := s.ListNetworks()
   315  
   316  	// then
   317  	require.NoError(t, err)
   318  	assert.Equal(t, []string{"toml"}, nets)
   319  }
   320  
   321  func testFileStoreV1DeleteNetworkSucceeds(t *testing.T) {
   322  	vegaHome := newVegaHome(t)
   323  
   324  	// Create a network for us to delete
   325  	s, err := v1.InitialiseStore(vegaHome)
   326  	require.NoError(t, err)
   327  	assert.NotNil(t, s)
   328  
   329  	net := &network.Network{
   330  		Name: "test",
   331  	}
   332  
   333  	err = s.SaveNetwork(net)
   334  	require.NoError(t, err)
   335  
   336  	// Check it's really there
   337  	returnedNet, err := s.GetNetwork("test")
   338  	require.NoError(t, err)
   339  	assert.Equal(t, net, returnedNet)
   340  
   341  	// Now delete it
   342  	err = s.DeleteNetwork("test")
   343  	require.NoError(t, err)
   344  
   345  	// Check it's no longer there
   346  	returnedNet, err = s.GetNetwork("test")
   347  	require.Error(t, err)
   348  	assert.Nil(t, returnedNet)
   349  }
   350  
   351  func testFileStoreV1RenamingNetworkSucceeds(t *testing.T) {
   352  	vegaHome := newVegaHome(t)
   353  
   354  	// Create a network for us to rename
   355  	s, err := v1.InitialiseStore(vegaHome)
   356  	require.NoError(t, err)
   357  	assert.NotNil(t, s)
   358  
   359  	// given
   360  	net := &network.Network{
   361  		Name: "test",
   362  	}
   363  
   364  	// when
   365  	err = s.SaveNetwork(net)
   366  
   367  	// then
   368  	require.NoError(t, err)
   369  	vgtest.AssertFileAccess(t, s.GetNetworkPath(net.Name))
   370  
   371  	// given
   372  	newName := vgrand.RandomStr(5)
   373  
   374  	// when
   375  	err = s.RenameNetwork(net.Name, newName)
   376  
   377  	// then
   378  	assert.NoError(t, err)
   379  	vgtest.AssertNoFile(t, s.GetNetworkPath(net.Name))
   380  	vgtest.AssertFileAccess(t, s.GetNetworkPath(newName))
   381  
   382  	// when
   383  	w1, err := s.GetNetwork(net.Name)
   384  
   385  	// then
   386  	assert.Error(t, err, api.ErrNetworkDoesNotExist)
   387  	assert.Nil(t, w1)
   388  
   389  	// when
   390  	w2, err := s.GetNetwork(newName)
   391  
   392  	// then
   393  	require.NoError(t, err)
   394  	assert.NotEmpty(t, w2)
   395  }
   396  
   397  func testFileStoreV1RenamingNonExistingNetworkFails(t *testing.T) {
   398  	vegaHome := newVegaHome(t)
   399  
   400  	// given
   401  	s, err := v1.InitialiseStore(vegaHome)
   402  	require.NoError(t, err)
   403  	assert.NotNil(t, s)
   404  
   405  	// given
   406  	unknownName := vgrand.RandomStr(5)
   407  	newName := vgrand.RandomStr(5)
   408  
   409  	// when
   410  	err = s.RenameNetwork(unknownName, newName)
   411  
   412  	// then
   413  	assert.ErrorIs(t, err, api.ErrNetworkDoesNotExist)
   414  	vgtest.AssertNoFile(t, s.GetNetworkPath(unknownName))
   415  	vgtest.AssertNoFile(t, s.GetNetworkPath(newName))
   416  }
   417  
   418  func testFileStoreV1RenamingNetworkWithInvalidNameFails(t *testing.T) {
   419  	vegaHome := newVegaHome(t)
   420  
   421  	// given
   422  	s, err := v1.InitialiseStore(vegaHome)
   423  	require.NoError(t, err)
   424  	assert.NotNil(t, s)
   425  
   426  	// given
   427  	net := &network.Network{
   428  		Name: "test",
   429  	}
   430  
   431  	// when
   432  	err = s.SaveNetwork(net)
   433  
   434  	// then
   435  	require.NoError(t, err)
   436  	vgtest.AssertFileAccess(t, s.GetNetworkPath(net.Name))
   437  
   438  	tcs := []struct {
   439  		name    string
   440  		newName string
   441  		err     error
   442  	}{
   443  		{
   444  			name:    "empty",
   445  			newName: "",
   446  			err:     v1.ErrNetworkNameCannotBeEmpty,
   447  		}, {
   448  			name:    "starting with a dot",
   449  			newName: ".start-with-dot",
   450  			err:     v1.ErrNetworkNameCannotStartWithDot,
   451  		}, {
   452  			name:    "containing slashes",
   453  			newName: "contains/multiple/slashes/",
   454  			err:     v1.ErrNetworkNameCannotContainSlash,
   455  		}, {
   456  			name:    "containing back-slashes",
   457  			newName: "contains\\multiple\\slashes\\",
   458  			err:     v1.ErrNetworkNameCannotContainSlash,
   459  		},
   460  	}
   461  
   462  	for _, tc := range tcs {
   463  		t.Run(tc.name, func(tt *testing.T) {
   464  			// when
   465  			err := s.RenameNetwork(net.Name, tc.newName)
   466  
   467  			// then
   468  			require.ErrorIs(tt, err, tc.err)
   469  			vgtest.AssertNoFile(tt, s.GetNetworkPath(tc.newName))
   470  		})
   471  	}
   472  }
   473  
   474  func initialiseFromPath(t *testing.T, vegaHome paths.Paths) *v1.FileStore {
   475  	t.Helper()
   476  	s, err := v1.InitialiseStore(vegaHome)
   477  	if err != nil {
   478  		t.Fatalf("couldn't initialise store: %v", err)
   479  	}
   480  	return s
   481  }
   482  
   483  func newVegaHome(t *testing.T) *paths.CustomPaths {
   484  	t.Helper()
   485  	return &paths.CustomPaths{CustomHome: t.TempDir()}
   486  }
   487  
   488  func networksHome(t *testing.T, vegaHome *paths.CustomPaths) string {
   489  	t.Helper()
   490  	return vegaHome.ConfigPathFor(paths.WalletServiceNetworksConfigHome)
   491  }
   492  
   493  func networkPath(t *testing.T, vegaHome *paths.CustomPaths, name string) string {
   494  	t.Helper()
   495  	return filepath.Join(networksHome(t, vegaHome), name+".toml")
   496  }