github.com/Finschia/finschia-sdk@v0.48.1/server/oc_cmds_test.go (about)

     1  package server
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/require"
    12  
    13  	cfg "github.com/Finschia/ostracon/config"
    14  	"github.com/Finschia/ostracon/crypto"
    15  	tmjson "github.com/Finschia/ostracon/libs/json"
    16  	"github.com/Finschia/ostracon/libs/log"
    17  	tmos "github.com/Finschia/ostracon/libs/os"
    18  	tmrand "github.com/Finschia/ostracon/libs/rand"
    19  	"github.com/Finschia/ostracon/p2p"
    20  	"github.com/Finschia/ostracon/privval"
    21  	"github.com/Finschia/ostracon/types"
    22  	tmtime "github.com/Finschia/ostracon/types/time"
    23  )
    24  
    25  var (
    26  	logger = log.NewOCLogger(log.NewSyncWriter(os.Stdout))
    27  )
    28  
    29  func TestShowValidator(t *testing.T) {
    30  	testCommon := newPrecedenceCommon(t)
    31  
    32  	serverCtx := &Context{}
    33  	ctx := context.WithValue(context.Background(), ServerContextKey, serverCtx)
    34  
    35  	if err := testCommon.cmd.ExecuteContext(ctx); err != cancelledInPreRun {
    36  		t.Fatalf("function failed with [%T] %v", err, err)
    37  	}
    38  
    39  	// ostracon init & create the server config file
    40  	initFilesWithConfig(serverCtx.Config)
    41  	output := captureStdout(t, func() { ShowValidatorCmd().ExecuteContext(ctx) })
    42  
    43  	// output must match the locally stored priv_validator key
    44  	privKey := loadFilePVKey(t, serverCtx.Config.PrivValidatorKeyFile())
    45  	bz, err := tmjson.Marshal(privKey.PubKey)
    46  	require.NoError(t, err)
    47  	require.Equal(t, string(bz), output)
    48  }
    49  
    50  func TestShowValidatorWithKMS(t *testing.T) {
    51  	testCommon := newPrecedenceCommon(t)
    52  
    53  	serverCtx := &Context{}
    54  	ctx := context.WithValue(context.Background(), ServerContextKey, serverCtx)
    55  
    56  	if err := testCommon.cmd.ExecuteContext(ctx); err != cancelledInPreRun {
    57  		t.Fatalf("function failed with [%T] %v", err, err)
    58  	}
    59  
    60  	// ostracon init & create the server config file
    61  	serverCtx.Config.PrivValidatorRemoteAddresses = append(serverCtx.Config.PrivValidatorRemoteAddresses, "127.0.0.1")
    62  	initFilesWithConfig(serverCtx.Config)
    63  
    64  	chainID, err := loadChainID(serverCtx.Config)
    65  	require.NoError(t, err)
    66  
    67  	// remove config file
    68  	if tmos.FileExists(serverCtx.Config.PrivValidatorKeyFile()) {
    69  		err := os.Remove(serverCtx.Config.PrivValidatorKeyFile())
    70  		require.NoError(t, err)
    71  	}
    72  
    73  	privval.WithMockKMS(t, t.TempDir(), chainID, func(addr string, privKey crypto.PrivKey) {
    74  		serverCtx.Config.PrivValidatorListenAddr = addr
    75  		require.NoFileExists(t, serverCtx.Config.PrivValidatorKeyFile())
    76  		output := captureStdout(t, func() { ShowValidatorCmd().ExecuteContext(ctx) })
    77  		require.NoError(t, err)
    78  
    79  		// output must contains the KMS public key
    80  		bz, err := tmjson.Marshal(privKey.PubKey())
    81  		require.NoError(t, err)
    82  		expected := string(bz)
    83  		require.Contains(t, output, expected)
    84  	})
    85  }
    86  
    87  func TestShowValidatorWithInefficientKMSAddress(t *testing.T) {
    88  	testCommon := newPrecedenceCommon(t)
    89  
    90  	serverCtx := &Context{}
    91  	ctx := context.WithValue(context.Background(), ServerContextKey, serverCtx)
    92  
    93  	if err := testCommon.cmd.ExecuteContext(ctx); err != cancelledInPreRun {
    94  		t.Fatalf("function failed with [%T] %v", err, err)
    95  	}
    96  
    97  	// ostracon init & create the server config file
    98  	initFilesWithConfig(serverCtx.Config)
    99  
   100  	// remove config file
   101  	if tmos.FileExists(serverCtx.Config.PrivValidatorKeyFile()) {
   102  		err := os.Remove(serverCtx.Config.PrivValidatorKeyFile())
   103  		require.NoError(t, err)
   104  	}
   105  
   106  	serverCtx.Config.PrivValidatorListenAddr = "127.0.0.1:inefficient"
   107  	err := ShowValidatorCmd().ExecuteContext(ctx)
   108  	require.Error(t, err)
   109  }
   110  
   111  func TestLoadChainID(t *testing.T) {
   112  	expected := "c57861"
   113  	config := cfg.ResetTestRootWithChainID("TestLoadChainID", expected)
   114  	defer func() {
   115  		var _ = os.RemoveAll(config.RootDir)
   116  	}()
   117  
   118  	require.FileExists(t, config.GenesisFile())
   119  	genDoc, err := types.GenesisDocFromFile(config.GenesisFile())
   120  	require.NoError(t, err)
   121  	require.Equal(t, expected, genDoc.ChainID)
   122  
   123  	chainID, err := loadChainID(config)
   124  	require.NoError(t, err)
   125  	require.Equal(t, expected, chainID)
   126  }
   127  
   128  func TestLoadChainIDWithoutStateDB(t *testing.T) {
   129  	expected := "c34091"
   130  	config := cfg.ResetTestRootWithChainID("TestLoadChainID", expected)
   131  	defer func() {
   132  		var _ = os.RemoveAll(config.RootDir)
   133  	}()
   134  
   135  	config.DBBackend = "goleveldb"
   136  	config.DBPath = "/../path with containing chars that cannot be used\\/:*?\"<>|\x00"
   137  
   138  	_, err := loadChainID(config)
   139  	require.Error(t, err)
   140  }
   141  
   142  func initFilesWithConfig(config *cfg.Config) error {
   143  	// private validator
   144  	privValKeyFile := config.PrivValidatorKeyFile()
   145  	privValStateFile := config.PrivValidatorStateFile()
   146  	var pv *privval.FilePV
   147  	if tmos.FileExists(privValKeyFile) {
   148  		pv = privval.LoadFilePV(privValKeyFile, privValStateFile)
   149  		logger.Info("Found private validator", "keyFile", privValKeyFile,
   150  			"stateFile", privValStateFile)
   151  	} else {
   152  		pv = privval.GenFilePV(privValKeyFile, privValStateFile)
   153  		if pv != nil {
   154  			pv.Save()
   155  		}
   156  		logger.Info("Generated private validator", "keyFile", privValKeyFile,
   157  			"stateFile", privValStateFile)
   158  	}
   159  
   160  	nodeKeyFile := config.NodeKeyFile()
   161  	if tmos.FileExists(nodeKeyFile) {
   162  		logger.Info("Found node key", "path", nodeKeyFile)
   163  	} else {
   164  		if _, err := p2p.LoadOrGenNodeKey(nodeKeyFile); err != nil {
   165  			return err
   166  		}
   167  		logger.Info("Generated node key", "path", nodeKeyFile)
   168  	}
   169  
   170  	// genesis file
   171  	genFile := config.GenesisFile()
   172  	if tmos.FileExists(genFile) {
   173  		logger.Info("Found genesis file", "path", genFile)
   174  	} else {
   175  		genDoc := types.GenesisDoc{
   176  			ChainID:         fmt.Sprintf("test-chain-%v", tmrand.Str(6)),
   177  			GenesisTime:     tmtime.Now(),
   178  			ConsensusParams: types.DefaultConsensusParams(),
   179  		}
   180  		pubKey, err := pv.GetPubKey()
   181  		if err != nil {
   182  			return fmt.Errorf("can't get pubkey: %w", err)
   183  		}
   184  		genDoc.Validators = []types.GenesisValidator{{
   185  			Address: pubKey.Address(),
   186  			PubKey:  pubKey,
   187  			Power:   10,
   188  		}}
   189  
   190  		if err := genDoc.SaveAs(genFile); err != nil {
   191  			return err
   192  		}
   193  		logger.Info("Generated genesis file", "path", genFile)
   194  	}
   195  
   196  	return nil
   197  }
   198  
   199  func loadFilePVKey(t *testing.T, file string) privval.FilePVKey {
   200  	// output must match the locally stored priv_validator key
   201  	keyJSONBytes, err := ioutil.ReadFile(file)
   202  	require.NoError(t, err)
   203  	privKey := privval.FilePVKey{}
   204  	err = tmjson.Unmarshal(keyJSONBytes, &privKey)
   205  	require.NoError(t, err)
   206  	return privKey
   207  }
   208  
   209  func captureStdout(t *testing.T, fnc func()) string {
   210  	t.Helper()
   211  	backup := os.Stdout
   212  	defer func() {
   213  		os.Stdout = backup
   214  	}()
   215  	r, w, err := os.Pipe()
   216  	if err != nil {
   217  		t.Fatalf("fail pipe: %v", err)
   218  	}
   219  	os.Stdout = w
   220  	fnc()
   221  	w.Close()
   222  	var buffer bytes.Buffer
   223  	if n, err := buffer.ReadFrom(r); err != nil {
   224  		t.Fatalf("fail read buf: %v - number: %v", err, n)
   225  	}
   226  	output := buffer.String()
   227  	return output[:len(output)-1]
   228  }