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

     1  package accounts
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"math/rand"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"runtime"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/davecgh/go-spew/spew"
    16  )
    17  
    18  func tmpManager_CacheDB(t *testing.T) (string, *Manager) {
    19  	rand.Seed(time.Now().UnixNano())
    20  	dir, err := ioutil.TempDir("", fmt.Sprintf("eth-manager-cachedb-test-%d-%d", os.Getpid(), rand.Int()))
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  
    25  	m, err := NewManager(dir, veryLightScryptN, veryLightScryptP, true)
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  	return dir, m
    30  }
    31  
    32  func TestManager_DB(t *testing.T) {
    33  
    34  	dir, am := tmpManager_CacheDB(t)
    35  	defer os.RemoveAll(dir)
    36  
    37  	a, err := am.NewAccount("foo")
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	if !strings.HasPrefix(a.File, dir) {
    42  		t.Errorf("account file %s doesn't have dir prefix", a.File)
    43  	}
    44  	stat, err := os.Stat(a.File)
    45  	if err != nil {
    46  		t.Fatalf("account file %s doesn't exist (%v)", a.File, err)
    47  	}
    48  	if runtime.GOOS != "windows" && stat.Mode() != 0600 {
    49  		t.Fatalf("account file has wrong mode: got %o, want %o", stat.Mode(), 0600)
    50  	}
    51  	if !am.HasAddress(a.Address) {
    52  		t.Errorf("HasAddres(%x) should've returned true", a.Address)
    53  	}
    54  	if err := am.Update(a, "foo", "bar"); err != nil {
    55  		t.Errorf("Update error: %v", err)
    56  	}
    57  	if err := am.DeleteAccount(a, "bar"); err != nil {
    58  		t.Errorf("DeleteAccount error: %v", err)
    59  	}
    60  	if _, err := os.Stat(a.File); err == nil || !os.IsNotExist(err) {
    61  		t.Errorf("account file %s should be gone after DeleteAccount", a.File)
    62  	}
    63  	if am.HasAddress(a.Address) {
    64  		t.Errorf("HasAddress(%x) should've returned true after DeleteAccount", a.Address)
    65  	}
    66  	am.ac.close()
    67  	am = nil
    68  }
    69  
    70  func TestManager_Accounts_CacheDB(t *testing.T) {
    71  	// bug(whilei): I don't know why you have to do rm.
    72  	// Running the file as a standalone test is no problem.
    73  	// Running the suite (ie go test -v ./accounts/), it hangs here.
    74  	// Again, I think it has to do with test concurrency.
    75  	os.Remove(filepath.Join(cachetestDir, "accounts.db"))
    76  	am, err := NewManager(cachetestDir, LightScryptN, LightScryptP, true)
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  	am.ac.Syncfs2db(time.Now())
    81  	accounts := am.Accounts()
    82  	if !reflect.DeepEqual(accounts, cachedbtestAccounts) {
    83  		t.Fatalf("cachedb got initial accounts: %swant %s", spew.Sdump(accounts), spew.Sdump(cachedbtestAccounts))
    84  	}
    85  	am.ac.close()
    86  	am = nil
    87  }
    88  
    89  func TestManager_AccountsByIndex_CacheDB(t *testing.T) {
    90  	os.Remove(filepath.Join(cachetestDir, "accounts.db"))
    91  	am, err := NewManager(cachetestDir, LightScryptN, LightScryptP, true)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	am.ac.Syncfs2db(time.Now())
    96  
    97  	for i := range cachedbtestAccounts {
    98  		wantAccount := cachedbtestAccounts[i]
    99  		gotAccount, e := am.AccountByIndex(i)
   100  		if e != nil {
   101  			t.Fatalf("manager cache db #accountsbyindex: %v", e)
   102  		}
   103  		if !reflect.DeepEqual(wantAccount, gotAccount) {
   104  			t.Fatalf("got: %v, want: %v", spew.Sdump(gotAccount), spew.Sdump(wantAccount))
   105  		}
   106  	}
   107  	am.ac.close()
   108  	am = nil
   109  }
   110  
   111  func TestSignWithPassphrase_DB(t *testing.T) {
   112  	dir, am := tmpManager_CacheDB(t)
   113  	defer os.RemoveAll(dir)
   114  
   115  	pass := "passwd"
   116  	acc, err := am.NewAccount(pass)
   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  	_, err = am.SignWithPassphrase(acc.Address, pass, testSigData)
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	if _, unlocked := am.unlocked[acc.Address]; unlocked {
   131  		t.Fatal("expected account to be locked")
   132  	}
   133  
   134  	if _, err = am.SignWithPassphrase(acc.Address, "invalid passwd", testSigData); err == nil {
   135  		t.Fatal("expected SignHash to fail with invalid password")
   136  	}
   137  	am.ac.close()
   138  	am = nil
   139  }
   140  
   141  func TestTimedUnlock_DB(t *testing.T) {
   142  	dir, am := tmpManager_CacheDB(t)
   143  	defer os.RemoveAll(dir)
   144  
   145  	pass := "foo"
   146  	a1, err := am.NewAccount(pass)
   147  
   148  	// Signing without passphrase fails because account is locked
   149  	_, err = am.Sign(a1.Address, testSigData)
   150  	if err != ErrLocked {
   151  		t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err)
   152  	}
   153  
   154  	// Signing with passphrase works
   155  	if err = am.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	// Signing without passphrase works because account is temp unlocked
   160  	_, err = am.Sign(a1.Address, testSigData)
   161  	if err != nil {
   162  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   163  	}
   164  
   165  	// Signing fails again after automatic locking
   166  	time.Sleep(250 * time.Millisecond)
   167  	_, err = am.Sign(a1.Address, testSigData)
   168  	if err != ErrLocked {
   169  		t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
   170  	}
   171  	am.ac.close()
   172  	am = nil
   173  }
   174  
   175  func TestOverrideUnlock_DB(t *testing.T) {
   176  	dir, am := tmpManager_CacheDB(t)
   177  	defer os.RemoveAll(dir)
   178  
   179  	pass := "foo"
   180  	a1, err := am.NewAccount(pass)
   181  
   182  	// Unlock indefinitely.
   183  	if err = am.TimedUnlock(a1, pass, 5*time.Minute); err != nil {
   184  		t.Fatal(err)
   185  	}
   186  
   187  	// Signing without passphrase works because account is temp unlocked
   188  	_, err = am.Sign(a1.Address, testSigData)
   189  	if err != nil {
   190  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   191  	}
   192  
   193  	// reset unlock to a shorter period, invalidates the previous unlock
   194  	if err = am.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	// Signing without passphrase still works because account is temp unlocked
   199  	_, err = am.Sign(a1.Address, testSigData)
   200  	if err != nil {
   201  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   202  	}
   203  
   204  	// Signing fails again after automatic locking
   205  	time.Sleep(250 * time.Millisecond)
   206  	_, err = am.Sign(a1.Address, testSigData)
   207  	if err != ErrLocked {
   208  		t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
   209  	}
   210  	am.ac.close()
   211  	am = nil
   212  }
   213  
   214  // unlocks account from manager created in existing testdata/keystore dir
   215  func TestTimedUnlock_DB2(t *testing.T) {
   216  
   217  	am, err := NewManager(cachetestDir, veryLightScryptN, veryLightScryptP, true)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  
   222  	a1 := cachetestAccounts[1]
   223  
   224  	// Signing with passphrase works
   225  	if err := am.TimedUnlock(a1, "foobar", 100*time.Millisecond); err != nil {
   226  		t.Fatal(err)
   227  	}
   228  
   229  	// Signing without passphrase works because account is temp unlocked
   230  	_, err = am.Sign(a1.Address, testSigData)
   231  	if err != nil {
   232  		t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
   233  	}
   234  
   235  	// Signing fails again after automatic locking
   236  	time.Sleep(250 * time.Millisecond)
   237  	_, err = am.Sign(a1.Address, testSigData)
   238  	if err != ErrLocked {
   239  		t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
   240  	}
   241  	am.ac.close()
   242  	am = nil
   243  }
   244  
   245  // This test should fail under -race if signing races the expiration goroutine.
   246  func TestSignRace_DB(t *testing.T) {
   247  	dir, am := tmpManager_CacheDB(t)
   248  	defer os.RemoveAll(dir)
   249  
   250  	// Create a test account.
   251  	a1, err := am.NewAccount("")
   252  	if err != nil {
   253  		t.Fatal("could not create the test account", err)
   254  	}
   255  
   256  	if err := am.TimedUnlock(a1, "", 15*time.Millisecond); err != nil {
   257  		t.Fatal("could not unlock the test account", err)
   258  	}
   259  	end := time.Now().Add(500 * time.Millisecond)
   260  	for time.Now().Before(end) {
   261  		if _, err := am.Sign(a1.Address, testSigData); err == ErrLocked {
   262  			return
   263  		} else if err != nil {
   264  			t.Errorf("Sign error: %v", err)
   265  			return
   266  		}
   267  		time.Sleep(1 * time.Millisecond)
   268  	}
   269  	t.Error("Account did not lock within the timeout")
   270  	am.ac.close()
   271  	am = nil
   272  }