mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
196 lines
7.2 KiB
Go
196 lines
7.2 KiB
Go
// Copyright (C) 2022, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
package subnet
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/luxfi/cli/v2/internal/mocks"
|
|
"github.com/luxfi/cli/v2/pkg/application"
|
|
"github.com/luxfi/cli/v2/pkg/binutils"
|
|
"github.com/luxfi/cli/v2/pkg/config"
|
|
"github.com/luxfi/cli/v2/pkg/constants"
|
|
"github.com/luxfi/cli/v2/pkg/prompts"
|
|
"github.com/luxfi/cli/v2/pkg/ux"
|
|
"github.com/luxfi/netrunner/client"
|
|
"github.com/luxfi/netrunner/rpcpb"
|
|
luxlog "github.com/luxfi/log"
|
|
"github.com/luxfi/node/v2/v2/utils/perms"
|
|
"github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
var (
|
|
testBlockChainID1 = "S4mBqKYypXfnCX7drcacHmSJFneYYrqCTfq3fkVwPnPHVqQ2y"
|
|
testBlockChainID2 = "11111111111111111111111111111111LpoYY"
|
|
testSubnetID1 = "XDnPSGJr2XmkkFaBEGcKFmJgtH8Fv7rNa6YFRKxCHQsUV6Egp"
|
|
testSubnetID2 = "2LSwchh6dK64RtGRXVdjyDd9YPu89mXB2MMjpZ1dDvnKZDYyro"
|
|
|
|
testVMID = "tGBrM2SXkAdNsqzb3SaFZZWMNdzjjFEUKteheTa4dhUwnfQyu" // VM ID of "test"
|
|
testChainName = "test"
|
|
|
|
fakeWaitForHealthyResponse = &rpcpb.WaitForHealthyResponse{
|
|
ClusterInfo: &rpcpb.ClusterInfo{
|
|
Healthy: true, // currently actually not checked, should it, if CustomVMsHealthy already is?
|
|
CustomChainsHealthy: true,
|
|
NodeNames: []string{"testNode1", "testNode2"},
|
|
NodeInfos: map[string]*rpcpb.NodeInfo{
|
|
"testNode1": {
|
|
Name: "testNode1",
|
|
Uri: "http://fake.localhost:12345",
|
|
},
|
|
"testNode2": {
|
|
Name: "testNode2",
|
|
Uri: "http://fake.localhost:12345",
|
|
},
|
|
},
|
|
CustomChains: map[string]*rpcpb.CustomChainInfo{
|
|
"bchain1": {
|
|
ChainId: testBlockChainID1,
|
|
},
|
|
"bchain2": {
|
|
ChainId: testBlockChainID2,
|
|
},
|
|
},
|
|
Subnets: map[string]*rpcpb.SubnetInfo{
|
|
testSubnetID1: {},
|
|
testSubnetID2: {},
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
func setupTest(t *testing.T) *require.Assertions {
|
|
// use io.Discard to not print anything
|
|
ux.NewUserLog(luxlog.NewNoOpLogger(), io.Discard)
|
|
return require.New(t)
|
|
}
|
|
|
|
func TestDeployToLocal(t *testing.T) {
|
|
require := setupTest(t)
|
|
luxVersion := "v1.18.0"
|
|
|
|
// fake-return true simulating the process is running
|
|
procChecker := &mocks.ProcessChecker{}
|
|
procChecker.On("IsServerProcessRunning", mock.Anything).Return(true, nil)
|
|
|
|
tmpDir := os.TempDir()
|
|
testDir, err := os.MkdirTemp(tmpDir, "local-test")
|
|
require.NoError(err)
|
|
defer func() {
|
|
err = os.RemoveAll(testDir)
|
|
require.NoError(err)
|
|
}()
|
|
|
|
app := &application.Lux{}
|
|
app.Setup(testDir, luxlog.NewNoOpLogger(), config.New(), prompts.NewPrompter(), application.NewDownloader())
|
|
|
|
binDir := filepath.Join(app.GetLuxBinDir(), "node-"+luxVersion)
|
|
|
|
// create a dummy plugins dir, deploy will check it exists
|
|
binChecker := &mocks.BinaryChecker{}
|
|
err = os.MkdirAll(filepath.Join(binDir, "plugins"), perms.ReadWriteExecute)
|
|
require.NoError(err)
|
|
|
|
// create a dummy node file, deploy will check it exists
|
|
f, err := os.Create(filepath.Join(binDir, "node"))
|
|
require.NoError(err)
|
|
defer func() {
|
|
_ = f.Close()
|
|
}()
|
|
|
|
binChecker.On("ExistsWithLatestVersion", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(true, tmpDir, nil)
|
|
|
|
binDownloader := &mocks.PluginBinaryDownloader{}
|
|
binDownloader.On("Download", mock.Anything, mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(nil)
|
|
binDownloader.On("InstallVM", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
|
|
|
testDeployer := &LocalDeployer{
|
|
procChecker: procChecker,
|
|
binChecker: binChecker,
|
|
getClientFunc: getTestClientFunc,
|
|
binaryDownloader: binDownloader,
|
|
app: app,
|
|
setDefaultSnapshot: fakeSetDefaultSnapshot,
|
|
luxVersion: luxVersion,
|
|
}
|
|
|
|
// create a simple genesis for the test
|
|
genesis := `{"config":{"chainId":9999},"gasLimit":"0x0","difficulty":"0x0","alloc":{}}`
|
|
// create a dummy genesis file, deploy will check it exists
|
|
testGenesis, err := os.CreateTemp(tmpDir, "test-genesis.json")
|
|
require.NoError(err)
|
|
err = os.WriteFile(testGenesis.Name(), []byte(genesis), constants.DefaultPerms755)
|
|
require.NoError(err)
|
|
// create dummy sidecar file, also checked by deploy
|
|
sidecar := `{"VM": "EVM"}`
|
|
testSubnetDir := filepath.Join(testDir, constants.SubnetDir, testChainName)
|
|
err = os.MkdirAll(testSubnetDir, constants.DefaultPerms755)
|
|
require.NoError(err)
|
|
testSidecar, err := os.Create(filepath.Join(testSubnetDir, constants.SidecarFileName))
|
|
require.NoError(err)
|
|
err = os.WriteFile(testSidecar.Name(), []byte(sidecar), constants.DefaultPerms755)
|
|
require.NoError(err)
|
|
// test actual deploy
|
|
s, b, err := testDeployer.DeployToLocalNetwork(testChainName, []byte(genesis), testGenesis.Name())
|
|
require.NoError(err)
|
|
require.Equal(testSubnetID2, s.String())
|
|
require.Equal(testBlockChainID2, b.String())
|
|
}
|
|
|
|
func TestGetLatestLuxVersion(t *testing.T) {
|
|
require := setupTest(t)
|
|
|
|
testVersion := "v1.99.9999"
|
|
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
resp := fmt.Sprintf(`{"some":"unimportant","fake":"data","tag_name":"%s","tag_name_was":"what we are interested in"}`, testVersion)
|
|
_, err := w.Write([]byte(resp))
|
|
require.NoError(err)
|
|
})
|
|
s := httptest.NewServer(testHandler)
|
|
defer s.Close()
|
|
|
|
dl := application.NewDownloader()
|
|
v, err := dl.GetLatestReleaseVersion(s.URL)
|
|
require.NoError(err)
|
|
require.Equal(v, testVersion)
|
|
}
|
|
|
|
func getTestClientFunc(...binutils.GRPCClientOpOption) (client.Client, error) {
|
|
c := &mocks.Client{}
|
|
fakeLoadSnapshotResponse := &rpcpb.LoadSnapshotResponse{}
|
|
fakeSaveSnapshotResponse := &rpcpb.SaveSnapshotResponse{}
|
|
fakeRemoveSnapshotResponse := &rpcpb.RemoveSnapshotResponse{}
|
|
fakeCreateBlockchainsResponse := &rpcpb.CreateBlockchainsResponse{}
|
|
c.On("LoadSnapshot", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(fakeLoadSnapshotResponse, nil)
|
|
c.On("SaveSnapshot", mock.Anything, mock.Anything).Return(fakeSaveSnapshotResponse, nil)
|
|
c.On("RemoveSnapshot", mock.Anything, mock.Anything).Return(fakeRemoveSnapshotResponse, nil)
|
|
c.On("CreateBlockchains", mock.Anything, mock.Anything, mock.Anything).Return(fakeCreateBlockchainsResponse, nil)
|
|
c.On("URIs", mock.Anything).Return([]string{"fakeUri"}, nil)
|
|
// When fake deploying, the first response needs to have a bogus subnet ID, because
|
|
// otherwise the doDeploy function "aborts" when checking if the subnet had already been deployed.
|
|
// Afterwards, we can set the actual VM ID so that the test returns an expected subnet ID...
|
|
|
|
// Return a fake wait for healthy response twice
|
|
c.On("WaitForHealthy", mock.Anything).Return(fakeWaitForHealthyResponse, nil).Twice()
|
|
// Afterwards, change the VmId so that TestDeployToLocal has the correct ID to check
|
|
alteredFakeResponse := proto.Clone(fakeWaitForHealthyResponse).(*rpcpb.WaitForHealthyResponse) // new(rpcpb.WaitForHealthyResponse)
|
|
alteredFakeResponse.ClusterInfo.CustomChains["bchain2"].VmId = testVMID
|
|
alteredFakeResponse.ClusterInfo.CustomChains["bchain2"].ChainName = testChainName
|
|
alteredFakeResponse.ClusterInfo.CustomChains["bchain1"].ChainName = "bchain1"
|
|
c.On("WaitForHealthy", mock.Anything).Return(alteredFakeResponse, nil)
|
|
c.On("Close").Return(nil)
|
|
return c, nil
|
|
}
|
|
|
|
func fakeSetDefaultSnapshot(string, bool) error {
|
|
return nil
|
|
}
|