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 }