<commit_before>// Package testing implements the base level testing types needed.
package testing

import (
	"bytes"
	"context"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"

	gethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/status-im/status-go/geth/common"
	"github.com/status-im/status-go/geth/params"
	assertions "github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
)

var (
	// TestConfig defines the default config usable at package-level.
	TestConfig *common.TestConfig

	// RootDir is the main application directory
	RootDir string

	// TestDataDir is data directory used for tests
	TestDataDir string

	// TestNetworkNames network ID to name mapping
	TestNetworkNames = map[int]string{
		params.MainNetworkID:    "Mainnet",
		params.RopstenNetworkID: "Ropsten",
		params.RinkebyNetworkID: "Rinkeby",
	}
)

func init() {
	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	// setup root directory
	RootDir = filepath.Dir(pwd)
	if strings.HasSuffix(RootDir, "geth") || strings.HasSuffix(RootDir, "cmd") { // we need to hop one more level
		RootDir = filepath.Join(RootDir, "..")
	}

	// setup auxiliary directories
	TestDataDir = filepath.Join(RootDir, ".ethereumtest")

	TestConfig, err = common.LoadTestConfig()
	if err != nil {
		panic(err)
	}
}

// BaseTestSuite defines a base tests suit which others suites can embedded to
// access initialization methods useful for testing.
type BaseTestSuite struct {
	suite.Suite
	NodeManager common.NodeManager
}

// StartTestNode initiazes a NodeManager instances with configuration retrieved
// from the test config.
func (s *BaseTestSuite) StartTestNode(networkID int, opts ...TestNodeOption) {
	require := s.Require()
	require.NotNil(s.NodeManager)

	nodeConfig, err := MakeTestNodeConfig(networkID)
	require.NoError(err)

	// Apply any options altering node config.
	for i := range opts {
		opts[i](nodeConfig)
	}

	keyStoreDir := filepath.Join(TestDataDir, TestNetworkNames[networkID], "keystore")
	require.NoError(common.ImportTestAccount(keyStoreDir, "test-account1.pk"))
	require.NoError(common.ImportTestAccount(keyStoreDir, "test-account2.pk"))

	require.False(s.NodeManager.IsNodeRunning())
	nodeStarted, err := s.NodeManager.StartNode(nodeConfig)
	require.NoError(err)
	require.NotNil(nodeStarted)
	<-nodeStarted
	require.True(s.NodeManager.IsNodeRunning())
}

// TestNodeOption is a callback passed to StartTestNode which alters its config.
type TestNodeOption func(config *params.NodeConfig)

// WithUpstream returns TestNodeOption which enabled UpstreamConfig.
func WithUpstream(url string) TestNodeOption {
	return func(config *params.NodeConfig) {
		config.UpstreamConfig.Enabled = true
		config.UpstreamConfig.URL = url
	}
}

// StopTestNode attempts to stop initialized NodeManager.
func (s *BaseTestSuite) StopTestNode() {
	require := s.Require()
	require.NotNil(s.NodeManager)
	require.True(s.NodeManager.IsNodeRunning())
	nodeStopped, err := s.NodeManager.StopNode()
	require.NoError(err)
	<-nodeStopped
	require.False(s.NodeManager.IsNodeRunning())
}

// FirstBlockHash validates Attach operation for the NodeManager.
func FirstBlockHash(require *assertions.Assertions, nodeManager common.NodeManager, expectedHash string) {
	require.NotNil(nodeManager)

	var firstBlock struct {
		Hash gethcommon.Hash `json:"hash"`
	}

	// obtain RPC client for running node
	runningNode, err := nodeManager.Node()
	require.NoError(err)
	require.NotNil(runningNode)

	rpcClient, err := runningNode.Attach()
	require.NoError(err)

	// get first block
	err = rpcClient.CallContext(context.Background(), &firstBlock, "eth_getBlockByNumber", "0x0", true)
	require.NoError(err)

	require.Equal(expectedHash, firstBlock.Hash.Hex())
}

// MakeTestNodeConfig defines a function to return a giving params.NodeConfig
// where specific network addresses are assigned based on provieded network id.
func MakeTestNodeConfig(networkID int) (*params.NodeConfig, error) {
	testDir := filepath.Join(TestDataDir, TestNetworkNames[networkID])

	if runtime.GOOS == "windows" {
		testDir = filepath.ToSlash(testDir)
	}

	configJSON := `{
		"NetworkId": ` + strconv.Itoa(networkID) + `,
		"DataDir": "` + testDir + `",
		"HTTPPort": ` + strconv.Itoa(TestConfig.Node.HTTPPort) + `,
		"WSPort": ` + strconv.Itoa(TestConfig.Node.WSPort) + `,
		"LogLevel": "INFO"
	}`

	nodeConfig, err := params.LoadNodeConfig(configJSON)
	if err != nil {
		return nil, err
	}
	return nodeConfig, nil
}

// LoadFromFile is useful for loading test data, from testdata/filename into a variable
// nolint: errcheck
func LoadFromFile(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}

	buf := bytes.NewBuffer(nil)
	io.Copy(buf, f)
	f.Close()

	return string(buf.Bytes())
}
<commit_msg>Add support for 'go test -v' flag for tests (#315)<commit_after>// Package testing implements the base level testing types needed.
package testing

import (
	"bytes"
	"context"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"

	gethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/status-im/status-go/geth/common"
	"github.com/status-im/status-go/geth/params"
	assertions "github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
	"testing"
)

var (
	// TestConfig defines the default config usable at package-level.
	TestConfig *common.TestConfig

	// RootDir is the main application directory
	RootDir string

	// TestDataDir is data directory used for tests
	TestDataDir string

	// TestNetworkNames network ID to name mapping
	TestNetworkNames = map[int]string{
		params.MainNetworkID:    "Mainnet",
		params.RopstenNetworkID: "Ropsten",
		params.RinkebyNetworkID: "Rinkeby",
	}
)

func init() {
	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	// setup root directory
	RootDir = filepath.Dir(pwd)
	if strings.HasSuffix(RootDir, "geth") || strings.HasSuffix(RootDir, "cmd") { // we need to hop one more level
		RootDir = filepath.Join(RootDir, "..")
	}

	// setup auxiliary directories
	TestDataDir = filepath.Join(RootDir, ".ethereumtest")

	TestConfig, err = common.LoadTestConfig()
	if err != nil {
		panic(err)
	}
}

// BaseTestSuite defines a base tests suit which others suites can embedded to
// access initialization methods useful for testing.
type BaseTestSuite struct {
	suite.Suite
	NodeManager common.NodeManager
}

// StartTestNode initiazes a NodeManager instances with configuration retrieved
// from the test config.
func (s *BaseTestSuite) StartTestNode(networkID int, opts ...TestNodeOption) {
	require := s.Require()
	require.NotNil(s.NodeManager)

	nodeConfig, err := MakeTestNodeConfig(networkID)
	require.NoError(err)

	// Apply any options altering node config.
	for i := range opts {
		opts[i](nodeConfig)
	}

	keyStoreDir := filepath.Join(TestDataDir, TestNetworkNames[networkID], "keystore")
	require.NoError(common.ImportTestAccount(keyStoreDir, "test-account1.pk"))
	require.NoError(common.ImportTestAccount(keyStoreDir, "test-account2.pk"))

	require.False(s.NodeManager.IsNodeRunning())
	nodeStarted, err := s.NodeManager.StartNode(nodeConfig)
	require.NoError(err)
	require.NotNil(nodeStarted)
	<-nodeStarted
	require.True(s.NodeManager.IsNodeRunning())
}

// TestNodeOption is a callback passed to StartTestNode which alters its config.
type TestNodeOption func(config *params.NodeConfig)

// WithUpstream returns TestNodeOption which enabled UpstreamConfig.
func WithUpstream(url string) TestNodeOption {
	return func(config *params.NodeConfig) {
		config.UpstreamConfig.Enabled = true
		config.UpstreamConfig.URL = url
	}
}

// StopTestNode attempts to stop initialized NodeManager.
func (s *BaseTestSuite) StopTestNode() {
	require := s.Require()
	require.NotNil(s.NodeManager)
	require.True(s.NodeManager.IsNodeRunning())
	nodeStopped, err := s.NodeManager.StopNode()
	require.NoError(err)
	<-nodeStopped
	require.False(s.NodeManager.IsNodeRunning())
}

// FirstBlockHash validates Attach operation for the NodeManager.
func FirstBlockHash(require *assertions.Assertions, nodeManager common.NodeManager, expectedHash string) {
	require.NotNil(nodeManager)

	var firstBlock struct {
		Hash gethcommon.Hash `json:"hash"`
	}

	// obtain RPC client for running node
	runningNode, err := nodeManager.Node()
	require.NoError(err)
	require.NotNil(runningNode)

	rpcClient, err := runningNode.Attach()
	require.NoError(err)

	// get first block
	err = rpcClient.CallContext(context.Background(), &firstBlock, "eth_getBlockByNumber", "0x0", true)
	require.NoError(err)

	require.Equal(expectedHash, firstBlock.Hash.Hex())
}

// MakeTestNodeConfig defines a function to return a giving params.NodeConfig
// where specific network addresses are assigned based on provieded network id.
func MakeTestNodeConfig(networkID int) (*params.NodeConfig, error) {
	testDir := filepath.Join(TestDataDir, TestNetworkNames[networkID])

	if runtime.GOOS == "windows" {
		testDir = filepath.ToSlash(testDir)
	}

	// run tests with "INFO" log level only
	// when `go test` invoked with `-v` flag
	errorLevel := "ERROR"
	if testing.Verbose() {
		errorLevel = "INFO"
	}

	configJSON := `{
		"NetworkId": ` + strconv.Itoa(networkID) + `,
		"DataDir": "` + testDir + `",
		"HTTPPort": ` + strconv.Itoa(TestConfig.Node.HTTPPort) + `,
		"WSPort": ` + strconv.Itoa(TestConfig.Node.WSPort) + `,
		"LogLevel": "` + errorLevel + `"
	}`

	nodeConfig, err := params.LoadNodeConfig(configJSON)
	if err != nil {
		return nil, err
	}
	return nodeConfig, nil
}

// LoadFromFile is useful for loading test data, from testdata/filename into a variable
// nolint: errcheck
func LoadFromFile(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}

	buf := bytes.NewBuffer(nil)
	io.Copy(buf, f)
	f.Close()

	return string(buf.Bytes())
}

{'fraction_non_alphanumeric': 0.1199796126401631, 'fraction_numerical': 0.0011213047910295616, 'mean_word_length': 4.72069970845481, 'pattern_counts': {'":': 10, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4787659', 'n_tokens_mistral': 3314, 'n_tokens_neox': 3218, 'n_words': 782}