github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/integration/integration.go (about)

     1  // Copyright Monax Industries Limited
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package integration
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"path"
    11  	"strconv"
    12  	"sync/atomic"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/hyperledger/burrow/acm"
    17  	"github.com/hyperledger/burrow/acm/validator"
    18  	"github.com/hyperledger/burrow/config"
    19  	"github.com/hyperledger/burrow/consensus/tendermint"
    20  	"github.com/hyperledger/burrow/core"
    21  	"github.com/hyperledger/burrow/execution"
    22  	"github.com/hyperledger/burrow/genesis"
    23  	"github.com/hyperledger/burrow/keys"
    24  	"github.com/hyperledger/burrow/logging"
    25  	"github.com/hyperledger/burrow/logging/logconfig"
    26  	"github.com/hyperledger/burrow/permission"
    27  	"github.com/hyperledger/burrow/rpc"
    28  	"github.com/hyperledger/burrow/testutil"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  const (
    33  	ChainName = "Integration_Test_Chain"
    34  )
    35  
    36  // Enable logger output during tests
    37  
    38  var node uint64 = 0
    39  
    40  func NoConsensus(conf *config.BurrowConfig) {
    41  	conf.Tendermint.Enabled = false
    42  }
    43  
    44  func CommitImmediately(conf *config.BurrowConfig) {
    45  	conf.Execution.TimeoutFactor = 0
    46  }
    47  
    48  func RunNode(t testing.TB, genesisDoc *genesis.GenesisDoc, privateAccounts []*acm.PrivateAccount,
    49  	options ...func(*config.BurrowConfig)) (kern *core.Kernel, shutdown func()) {
    50  
    51  	var err error
    52  	testConfig, cleanup := NewTestConfig(genesisDoc, options...)
    53  	// Uncomment for log output from tests
    54  	// testConfig.Logging = logconfig.New().Root(func(sink *logconfig.SinkConfig) *logconfig.SinkConfig {
    55  	//   return sink.SetOutput(logconfig.StderrOutput())
    56  	// })
    57  	testConfig.Logging = logconfig.New().Root(func(sink *logconfig.SinkConfig) *logconfig.SinkConfig {
    58  		return sink.SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch,
    59  			"total_validator")).SetOutput(logconfig.StdoutOutput())
    60  	})
    61  	kern, err = TestKernel(privateAccounts[0], privateAccounts, testConfig)
    62  	require.NoError(t, err)
    63  	err = kern.Boot()
    64  	require.NoError(t, err)
    65  	// Sometimes better to not shutdown as logging errors on shutdown may obscure real issue
    66  	return kern, func() {
    67  		Shutdown(kern)
    68  		cleanup()
    69  	}
    70  }
    71  
    72  func NewTestConfig(genesisDoc *genesis.GenesisDoc,
    73  	options ...func(*config.BurrowConfig)) (conf *config.BurrowConfig, cleanup func()) {
    74  
    75  	nodeNumber := atomic.AddUint64(&node, 1)
    76  	name := fmt.Sprintf("node_%03d", nodeNumber)
    77  	conf = config.DefaultBurrowConfig()
    78  	conf.Logging = nil
    79  	testDir, cleanup := testutil.EnterTestDirectory()
    80  	conf.BurrowDir = path.Join(testDir, fmt.Sprintf(".burrow_%s", name))
    81  	conf.GenesisDoc = genesisDoc
    82  	conf.Tendermint.Moniker = name
    83  	// Make blocks for purposes of tests
    84  	conf.Tendermint.CreateEmptyBlocks = tendermint.AlwaysCreateEmptyBlocks
    85  	conf.Keys.RemoteAddress = ""
    86  	// Assign run of ports
    87  	const freeport = "0"
    88  	conf.Tendermint.ListenHost = rpc.LocalHost
    89  	conf.Tendermint.ListenPort = freeport
    90  	conf.RPC.GRPC.ListenHost = rpc.LocalHost
    91  	conf.RPC.GRPC.ListenPort = freeport
    92  	conf.RPC.Metrics.ListenHost = rpc.LocalHost
    93  	conf.RPC.Metrics.ListenPort = freeport
    94  	conf.RPC.Info.ListenHost = rpc.LocalHost
    95  	conf.RPC.Info.ListenPort = freeport
    96  	conf.RPC.Web3.ListenHost = rpc.LocalHost
    97  	conf.RPC.Web3.ListenPort = freeport
    98  	conf.Execution.TimeoutFactor = 0.5
    99  	conf.Execution.VMOptions = []execution.VMOption{}
   100  	for _, opt := range options {
   101  		if opt != nil {
   102  			opt(conf)
   103  		}
   104  	}
   105  	return conf, cleanup
   106  }
   107  
   108  // We use this to wrap tests
   109  func TestKernel(validatorAccount *acm.PrivateAccount, keysAccounts []*acm.PrivateAccount,
   110  	testConfig *config.BurrowConfig) (*core.Kernel, error) {
   111  
   112  	fmt.Println("Creating integration test Kernel...")
   113  
   114  	kern, err := core.NewKernel(testConfig.BurrowDir)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	logger := logging.NewNoopLogger()
   120  	kern.SetLogger(logger)
   121  	if testConfig.Logging != nil {
   122  		err := kern.LoadLoggerFromConfig(testConfig.Logging)
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  	}
   127  
   128  	kern.SetKeyClient(keys.NewLocalKeyClient(keys.NewMemoryKeyStore(keysAccounts...), logger))
   129  
   130  	err = kern.LoadExecutionOptionsFromConfig(testConfig.Execution)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	err = kern.LoadState(testConfig.GenesisDoc)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	privVal := tendermint.NewPrivValidatorMemory(validatorAccount, validatorAccount)
   141  
   142  	err = kern.LoadTendermintFromConfig(testConfig, privVal)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	kern.AddProcesses(core.DefaultProcessLaunchers(kern, testConfig.RPC, testConfig.Keys)...)
   148  	return kern, nil
   149  }
   150  
   151  // TestGenesisDoc creates genesis from a set of accounts
   152  // and validators from indices within that slice
   153  func TestGenesisDoc(addressables []*acm.PrivateAccount, vals ...int) *genesis.GenesisDoc {
   154  	accounts := make(map[string]*acm.Account, len(addressables))
   155  	for i, pa := range addressables {
   156  		account := acm.FromAddressable(pa)
   157  		account.Balance += 1 << 32
   158  		account.Permissions = permission.AllAccountPermissions.Clone()
   159  		accounts[fmt.Sprintf("user_%v", i)] = account
   160  	}
   161  	genesisTime, err := time.Parse("02-01-2006", "27-10-2017")
   162  	if err != nil {
   163  		panic("could not parse test genesis time")
   164  	}
   165  
   166  	validators := make(map[string]*validator.Validator)
   167  	for _, i := range vals {
   168  		name := fmt.Sprintf("user_%d", i)
   169  		validators[name] = validator.FromAccount(accounts[name], 1<<16)
   170  		// Tendermint validators use a different addressing scheme for secp256k1
   171  		accounts[name].Address = validators[name].GetAddress()
   172  	}
   173  
   174  	return genesis.MakeGenesisDocFromAccounts(ChainName, nil, genesisTime, accounts, validators)
   175  }
   176  
   177  // Default deterministic account generation helper, pass number of accounts to make
   178  func MakePrivateAccounts(sec string, n int) []*acm.PrivateAccount {
   179  	accounts := make([]*acm.PrivateAccount, n)
   180  	for i := 0; i < n; i++ {
   181  		accounts[i] = acm.GeneratePrivateAccountFromSecret(sec + strconv.Itoa(i))
   182  	}
   183  	return accounts
   184  }
   185  
   186  func MakeEthereumAccounts(sec string, n int) []*acm.PrivateAccount {
   187  	accounts := make([]*acm.PrivateAccount, n)
   188  	for i := 0; i < n; i++ {
   189  		accounts[i] = acm.GenerateEthereumAccountFromSecret(sec + strconv.Itoa(i))
   190  	}
   191  	return accounts
   192  }
   193  
   194  func Shutdown(kern *core.Kernel) {
   195  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   196  	defer cancel()
   197  	err := kern.Shutdown(ctx)
   198  	if err != nil {
   199  		fmt.Fprintf(os.Stderr, "Error shutting down test kernel %v: %v", kern, err)
   200  	}
   201  }