github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/accounts/manager_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // +build !deterministic
    18  
    19  package accounts
    20  
    21  import (
    22  	"os"
    23  	"reflect"
    24  	"runtime"
    25  	"strings"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/davecgh/go-spew/spew"
    30  	"github.com/ethereumproject/go-ethereum/logger/glog"
    31  )
    32  
    33  func init() {
    34  	glog.SetD(0)
    35  	glog.SetV(0)
    36  }
    37  
    38  func TestManager_Mem(t *testing.T) {
    39  	dir, am := tmpManager(t)
    40  	defer os.RemoveAll(dir)
    41  
    42  	a, err := am.NewAccount("foo")
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	if !strings.HasPrefix(a.File, dir) {
    47  		t.Errorf("account file %s doesn't have dir prefix", a.File)
    48  	}
    49  	stat, err := os.Stat(a.File)
    50  	if err != nil {
    51  		t.Fatalf("account file %s doesn't exist (%v)", a.File, err)
    52  	}
    53  	if runtime.GOOS != "windows" && stat.Mode() != 0600 {
    54  		t.Fatalf("account file has wrong mode: got %o, want %o", stat.Mode(), 0600)
    55  	}
    56  	if !am.HasAddress(a.Address) {
    57  		t.Errorf("HasAddres(%x) should've returned true", a.Address)
    58  	}
    59  	if err := am.Update(a, "foo", "bar"); err != nil {
    60  		t.Errorf("Update error: %v", err)
    61  	}
    62  	if err := am.DeleteAccount(a, "bar"); err != nil {
    63  		t.Errorf("DeleteAccount error: %v", err)
    64  	}
    65  	if _, err := os.Stat(a.File); err == nil || !os.IsNotExist(err) {
    66  		t.Errorf("account file %s should be gone after DeleteAccount", a.File)
    67  	}
    68  	if am.HasAddress(a.Address) {
    69  		t.Errorf("HasAddress(%x) should've returned true after DeleteAccount", a.Address)
    70  	}
    71  }
    72  
    73  func TestManager_Accounts_Mem(t *testing.T) {
    74  	am, err := NewManager(cachetestDir, LightScryptN, LightScryptP, false)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	accounts := am.Accounts()
    79  	if !reflect.DeepEqual(accounts, cachetestAccounts) {
    80  		t.Fatalf("mem got initial accounts: %swant %s", spew.Sdump(accounts), spew.Sdump(cachetestAccounts))
    81  	}
    82  }
    83  
    84  func TestManager_AccountsByIndex(t *testing.T) {
    85  	am, err := NewManager(cachetestDir, LightScryptN, LightScryptP, false)
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  
    90  	for i := range cachetestAccounts {
    91  		wantAccount := cachetestAccounts[i]
    92  		gotAccount, e := am.AccountByIndex(i)
    93  		if e != nil {
    94  			t.Fatalf("manager cache mem #accountsbyindex: %v", e)
    95  		}
    96  		if !reflect.DeepEqual(wantAccount, gotAccount) {
    97  			t.Fatalf("want: %v, got: %v", wantAccount, gotAccount)
    98  		}
    99  	}
   100  }
   101  
   102  func TestSignWithPassphrase_Mem(t *testing.T) {
   103  	dir, am := tmpManager(t)
   104  	defer os.RemoveAll(dir)
   105  
   106  	pass := "passwd"
   107  	acc, err := am.NewAccount(pass)
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	if _, unlocked := am.unlocked[acc.Address]; unlocked {
   113  		t.Fatal("expected account to be locked")
   114  	}
   115  
   116  	_, err = am.SignWithPassphrase(acc.Address, pass, testSigData)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  
   121  	if _, unlocked := am.unlocked[acc.Address]; unlocked {
   122  		t.Fatal("expected account to be locked")
   123  	}
   124  
   125  	if _, err = am.SignWithPassphrase(acc.Address, "invalid passwd", testSigData); err == nil {
   126  		t.Fatal("expected SignHash to fail with invalid password")
   127  	}
   128  }
   129  
   130  // unlocks newly created account in temp dir
   131  func TestTimedUnlock_Mem(t *testing.T) {
   132  	dir, am := tmpManager(t)
   133  	defer os.RemoveAll(dir)
   134  
   135  	pass := "foo"
   136  	a1, err := am.NewAccount(pass)
   137  
   138  	// Signing without passphrase fails because account is locked
   139  	_, err = am.Sign(a1.Address, testSigData)
   140  	if err != ErrLocked {
   141  		t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err)
   142  	}
   143  
   144  	// Signing with passphrase works
   145  	if err = am.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	// Signing without passphrase works because account is temp unlocked
   150  	_, err = am.Sign(a1.Address, testSigData)
   151  	if err != nil {
   152  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   153  	}
   154  
   155  	// Signing fails again after automatic locking
   156  	time.Sleep(250 * time.Millisecond)
   157  	_, err = am.Sign(a1.Address, testSigData)
   158  	if err != ErrLocked {
   159  		t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
   160  	}
   161  }
   162  
   163  // unlocks account from manager created in existing testdata/keystore dir
   164  func TestTimedUnlock_Mem2(t *testing.T) {
   165  	am, err := NewManager(cachetestDir, veryLightScryptN, veryLightScryptP, false)
   166  	if err != nil {
   167  		t.Fatal(err)
   168  	}
   169  
   170  	a1 := cachetestAccounts[1]
   171  
   172  	// Signing with passphrase works
   173  	if err := am.TimedUnlock(a1, "foobar", 100*time.Millisecond); err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	// Signing without passphrase works because account is temp unlocked
   178  	_, err = am.Sign(a1.Address, testSigData)
   179  	if err != nil {
   180  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   181  	}
   182  
   183  	// Signing fails again after automatic locking
   184  	time.Sleep(250 * time.Millisecond)
   185  	_, err = am.Sign(a1.Address, testSigData)
   186  	if err != ErrLocked {
   187  		t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
   188  	}
   189  }
   190  
   191  func TestOverrideUnlock_Mem(t *testing.T) {
   192  	dir, am := tmpManager(t)
   193  	defer os.RemoveAll(dir)
   194  
   195  	pass := "foo"
   196  	a1, err := am.NewAccount(pass)
   197  
   198  	// Unlock indefinitely.
   199  	if err = am.TimedUnlock(a1, pass, 5*time.Minute); err != nil {
   200  		t.Fatal(err)
   201  	}
   202  
   203  	// Signing without passphrase works because account is temp unlocked
   204  	_, err = am.Sign(a1.Address, testSigData)
   205  	if err != nil {
   206  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   207  	}
   208  
   209  	// reset unlock to a shorter period, invalidates the previous unlock
   210  	if err = am.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil {
   211  		t.Fatal(err)
   212  	}
   213  
   214  	// Signing without passphrase still works because account is temp unlocked
   215  	_, err = am.Sign(a1.Address, testSigData)
   216  	if err != nil {
   217  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   218  	}
   219  
   220  	// Signing fails again after automatic locking
   221  	time.Sleep(250 * time.Millisecond)
   222  	_, err = am.Sign(a1.Address, testSigData)
   223  	if err != ErrLocked {
   224  		t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
   225  	}
   226  }
   227  
   228  // This test should fail under -race if signing races the expiration goroutine.
   229  func TestSignRace_Mem(t *testing.T) {
   230  	dir, am := tmpManager(t)
   231  	defer os.RemoveAll(dir)
   232  
   233  	// Create a test account.
   234  	a1, err := am.NewAccount("")
   235  	if err != nil {
   236  		t.Fatal("could not create the test account", err)
   237  	}
   238  
   239  	if err := am.TimedUnlock(a1, "", 15*time.Millisecond); err != nil {
   240  		t.Fatal("could not unlock the test account", err)
   241  	}
   242  	end := time.Now().Add(500 * time.Millisecond)
   243  	for time.Now().Before(end) {
   244  		if _, err := am.Sign(a1.Address, testSigData); err == ErrLocked {
   245  			return
   246  		} else if err != nil {
   247  			t.Errorf("Sign error: %v", err)
   248  			return
   249  		}
   250  		time.Sleep(1 * time.Millisecond)
   251  	}
   252  	t.Error("Account did not lock within the timeout")
   253  }