github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/geth/flag_test.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	"reflect"
    11  
    12  	"os/exec"
    13  
    14  	"github.com/ethereumproject/go-ethereum/accounts"
    15  	"github.com/ethereumproject/go-ethereum/common"
    16  	"github.com/ethereumproject/go-ethereum/core"
    17  	"github.com/ethereumproject/go-ethereum/logger/glog"
    18  	"gopkg.in/urfave/cli.v1"
    19  )
    20  
    21  var ogHome string  // placeholder
    22  var tmpHOME string // fake $HOME (for defaults)
    23  var tmpDir string  // temp DATA_DIR (inside tmpHOME)
    24  
    25  var app *cli.App
    26  var context *cli.Context
    27  
    28  var set *flag.FlagSet
    29  
    30  // globally available flags that go will parse, making them available for the mock app
    31  type flags []struct {
    32  	name    string
    33  	aliases []string
    34  	value   interface{}
    35  }
    36  
    37  var gFlags flags
    38  
    39  func init() {
    40  	glog.SetD(0)
    41  	glog.SetV(0)
    42  }
    43  
    44  func makeTmpDataDir(t *testing.T) {
    45  	ogHome = common.HomeDir()
    46  	var e error
    47  
    48  	tmpHOME, e = ioutil.TempDir(ogHome, "HOME")
    49  	if e != nil {
    50  		t.Fatalf("Failed to create temp directory in: %v", ogHome)
    51  	}
    52  
    53  	if e = os.Setenv("HOME", tmpHOME); e != nil {
    54  		t.Fatalf("Failed to temporarily set system home: %v", e)
    55  	}
    56  
    57  	td, err := ioutil.TempDir(tmpHOME, "DATADIR")
    58  	if err != nil {
    59  		t.Fatalf("Failed to create temp directory in: %v", tmpHOME)
    60  	}
    61  	tmpDir = td
    62  }
    63  
    64  func rmTmpDataDir(t *testing.T) {
    65  	if e := os.RemoveAll(tmpHOME); e != nil {
    66  		t.Fatalf("Failed to remove temp dir: %v", e)
    67  	}
    68  
    69  	if e := os.Setenv("HOME", ogHome); e != nil {
    70  		t.Fatalf("Failed to reset system home env var: %v", e)
    71  	}
    72  }
    73  
    74  func setupFlags(t *testing.T) {
    75  
    76  	gFlags = flags{
    77  		{"testnet", []string{}, false},
    78  		{"data-dir", []string{"datadir"}, common.DefaultDataDir()},
    79  		{"bootnodes", []string{}, ""},
    80  		{"chain", []string{}, ""},
    81  	}
    82  
    83  	app = makeCLIApp()
    84  	app.Writer = ioutil.Discard
    85  
    86  	set = flag.NewFlagSet("test", 0)
    87  
    88  	for _, f := range gFlags {
    89  		switch f.value.(type) {
    90  		case string:
    91  			set.String(f.name, f.value.(string), "")
    92  		case bool:
    93  			set.Bool(f.name, f.value.(bool), "")
    94  		case int:
    95  			set.Int(f.name, f.value.(int), "")
    96  		}
    97  
    98  		if len(f.aliases) > 0 {
    99  			for _, a := range f.aliases {
   100  				switch f.value.(type) {
   101  				case string:
   102  					set.String(a, f.value.(string), "")
   103  				case bool:
   104  					set.Bool(a, f.value.(bool), "")
   105  				case int:
   106  					set.Int(a, f.value.(int), "")
   107  				}
   108  			}
   109  		}
   110  	}
   111  }
   112  
   113  func TestMustMakeChainDataDir(t *testing.T) {
   114  
   115  	makeTmpDataDir(t)
   116  	defer rmTmpDataDir(t)
   117  
   118  	dd := common.DefaultDataDir()
   119  	funkyName := "my.private-chain_2chainz!"
   120  
   121  	cases := []struct {
   122  		flags []string
   123  		want  string
   124  		err   error
   125  	}{
   126  		{[]string{}, filepath.Join(dd, "mainnet"), nil},
   127  
   128  		{[]string{"--datadir", tmpDir}, filepath.Join(tmpDir, "mainnet"), nil},
   129  		{[]string{"--data-dir", tmpDir}, filepath.Join(tmpDir, "mainnet"), nil},
   130  
   131  		{[]string{"--testnet", "--data-dir", tmpDir}, filepath.Join(tmpDir, "morden"), nil},
   132  		{[]string{"--testnet"}, filepath.Join(dd, "morden"), nil},
   133  
   134  		{[]string{"--chain"}, "", ErrInvalidFlag},
   135  		{[]string{"--chain", "main"}, filepath.Join(dd, "mainnet"), nil},
   136  		{[]string{"--chain", "morden"}, filepath.Join(dd, "morden"), nil},
   137  		{[]string{"--chain", "testnet"}, filepath.Join(dd, "morden"), nil},
   138  		{[]string{"--chain", "kitty"}, filepath.Join(dd, "kitty"), nil},
   139  
   140  		{[]string{"--chain", "kitty/cat"}, filepath.Join(dd, "kitty", "cat"), nil},
   141  		{[]string{"--chain", funkyName}, filepath.Join(dd, funkyName), nil},
   142  	}
   143  
   144  	for _, c := range cases {
   145  		// Unset cache.
   146  		core.SetCacheChainIdentity("")
   147  
   148  		setupFlags(t)
   149  
   150  		if e := set.Parse(c.flags); e != nil {
   151  			if c.err == nil {
   152  				t.Fatal(e)
   153  			} else {
   154  				// don't compare the errors for now, this is enough
   155  				t.Log("got expected error/+usage info: ok\n(checks cli context flag parsing requires an argument)")
   156  				continue
   157  			}
   158  		}
   159  		context = cli.NewContext(app, set, nil)
   160  
   161  		got := MustMakeChainDataDir(context)
   162  
   163  		if c.err == nil && got != c.want {
   164  			t.Errorf("flag: %v, chaindir want: %v, got: %v", c.flags, c.want, got)
   165  		}
   166  		if c.err == nil && !filepath.IsAbs(got) {
   167  			t.Errorf("flag: %v, unexpected relative path: %v", c.flags, got)
   168  		}
   169  		if c.err != nil && got != "" {
   170  			t.Errorf("flag: %v, want: %v, got: %v", c.flags, c.err, got)
   171  		}
   172  	}
   173  }
   174  
   175  func TestGetChainIdentityValue(t *testing.T) {
   176  
   177  	cases := []struct {
   178  		flags []string
   179  		want  string
   180  	}{
   181  		// Known (defaulty) chain values.
   182  		{[]string{"--chain", "morden"}, "morden"},
   183  		{[]string{"--chain", "testnet"}, "morden"},
   184  		{[]string{"--chain", "main"}, "mainnet"},
   185  		{[]string{"--chain", "mainnet"}, "mainnet"},
   186  
   187  		// Custom.
   188  		{[]string{"--chain", "kitty"}, "kitty"},
   189  		{[]string{"--chain", "kitty/cat"}, filepath.Join("kitty", "cat")},
   190  
   191  		// Blacklisted.
   192  		{[]string{"--chain", "chaindata"}, ""},
   193  	}
   194  
   195  	for _, c := range cases {
   196  		// Unset cache.
   197  		core.SetCacheChainIdentity("")
   198  
   199  		setupFlags(t)
   200  
   201  		if e := set.Parse(c.flags); e != nil {
   202  			t.Fatal(e)
   203  		}
   204  		context = cli.NewContext(app, set, nil)
   205  
   206  		if c.want != "" {
   207  			got := mustMakeChainIdentity(context)
   208  			if c.want != got {
   209  				t.Fatalf("[%v] want: %v, got: %v", c.flags, c.want, got)
   210  			}
   211  		} else {
   212  			// https://stackoverflow.com/questions/26225513/how-to-test-os-exit-scenarios-in-go
   213  			if os.Getenv("DOES_GLOG_FATAL") == "1" {
   214  				mustMakeChainIdentity(context)
   215  				return
   216  			}
   217  			cmd := exec.Command(os.Args[0], "-test.run=TestGetChainIdentityValue")
   218  			cmd.Env = append(os.Environ(), "DOES_GLOG_FATAL=1")
   219  			err := cmd.Run()
   220  			if e, ok := err.(*exec.ExitError); ok && !e.Success() {
   221  				t.Log("expected osexit=1: ok", c.flags)
   222  				return
   223  			}
   224  			t.Fatalf("process ran with err %v, want exit status 1", err)
   225  		}
   226  
   227  	}
   228  }
   229  
   230  // Bootnodes flag parse 1
   231  func TestMakeBootstrapNodesFromContext1(t *testing.T) {
   232  
   233  	makeTmpDataDir(t)
   234  	defer rmTmpDataDir(t)
   235  	setupFlags(t)
   236  
   237  	arg := []string{
   238  		"--bootnodes",
   239  		"enode://6e538e7c1280f0a31ff08b382db5302480f775480b8e68f8febca0ceff81e4b19153c6f8bf60313b93bef2cc34d34e1df41317de0ce613a201d1660a788a03e2@52.206.67.235:30303",
   240  	}
   241  	if e := set.Parse(arg); e != nil {
   242  		t.Fatal(e)
   243  	}
   244  	context = cli.NewContext(app, set, nil)
   245  	got := MakeBootstrapNodesFromContext(context)
   246  	if len(got) != 1 {
   247  		t.Errorf("wanted: 1, got %v", len(got))
   248  	}
   249  	if got[0].IP.String() != "52.206.67.235" {
   250  		t.Errorf("unexpected: %v", got[0].IP.String())
   251  	}
   252  }
   253  
   254  // Bootnodes flag parse 2
   255  func TestMakeBootstrapNodesFromContext2(t *testing.T) {
   256  
   257  	makeTmpDataDir(t)
   258  	defer rmTmpDataDir(t)
   259  	setupFlags(t)
   260  
   261  	arg := []string{
   262  		"--bootnodes",
   263  		`enode://6e538e7c1280f0a31ff08b382db5302480f775480b8e68f8febca0ceff81e4b19153c6f8bf60313b93bef2cc34d34e1df41317de0ce613a201d1660a788a03e2@52.206.67.235:30303,enode://f50e675a34f471af2438b921914b5f06499c7438f3146f6b8936f1faeb50b8a91d0d0c24fb05a66f05865cd58c24da3e664d0def806172ddd0d4c5bdbf37747e@144.76.238.49:30306`,
   264  	}
   265  	if e := set.Parse(arg); e != nil {
   266  		t.Fatal(e)
   267  	}
   268  	context = cli.NewContext(app, set, nil)
   269  	got := MakeBootstrapNodesFromContext(context)
   270  	if len(got) != 2 {
   271  		t.Errorf("wanted: 2, got %v", len(got))
   272  	}
   273  	if got[0].IP.String() != "52.206.67.235" {
   274  		t.Errorf("unexpected: %v", got[0].IP.String())
   275  	}
   276  	if got[1].IP.String() != "144.76.238.49" {
   277  		t.Errorf("unexpected: %v", got[1].IP.String())
   278  	}
   279  }
   280  
   281  // Bootnodes default
   282  func TestMakeBootstrapNodesFromContext3(t *testing.T) {
   283  
   284  	makeTmpDataDir(t)
   285  	defer rmTmpDataDir(t)
   286  	setupFlags(t)
   287  
   288  	arg := []string{}
   289  	if e := set.Parse(arg); e != nil {
   290  		t.Fatal(e)
   291  	}
   292  	context = cli.NewContext(app, set, nil)
   293  	got := MakeBootstrapNodesFromContext(context)
   294  	if len(got) != len(core.DefaultConfigMainnet.ParsedBootstrap) {
   295  		t.Errorf("wanted: %v, got %v", len(core.DefaultConfigMainnet.ParsedBootstrap), len(got))
   296  	}
   297  }
   298  
   299  // Bootnodes testnet default
   300  func TestMakeBootstrapNodesFromContext4(t *testing.T) {
   301  
   302  	makeTmpDataDir(t)
   303  	defer rmTmpDataDir(t)
   304  	setupFlags(t)
   305  
   306  	arg := []string{"--testnet"}
   307  	if e := set.Parse(arg); e != nil {
   308  		t.Fatal(e)
   309  	}
   310  	context = cli.NewContext(app, set, nil)
   311  	got := MakeBootstrapNodesFromContext(context)
   312  	if len(got) != len(core.DefaultConfigMorden.ParsedBootstrap) {
   313  		t.Errorf("wanted: %v, got %v", len(core.DefaultConfigMorden.ParsedBootstrap), len(got))
   314  	}
   315  }
   316  
   317  func TestMakeAddress(t *testing.T) {
   318  	accAddr := "f466859ead1932d743d622cb74fc058882e8648a" // account[0] address
   319  	cachetestdir := filepath.Join("accounts", "testdata", "keystore")
   320  	am, err := accounts.NewManager(cachetestdir, accounts.LightScryptN, accounts.LightScryptP, false)
   321  	if err != nil {
   322  		t.Fatal(err)
   323  	}
   324  	gotAccount, e := MakeAddress(am, accAddr)
   325  	if e != nil {
   326  		t.Fatalf("makeaddress: %v", e)
   327  	}
   328  	wantAccount := accounts.Account{
   329  		Address: common.HexToAddress(accAddr),
   330  	}
   331  	// compare all
   332  	if !reflect.DeepEqual(wantAccount, gotAccount) {
   333  		t.Fatalf("want: %v, got: %v", wantAccount, gotAccount)
   334  	}
   335  }