github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/accounts/cachedb_test.go (about) 1 package accounts 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "reflect" 8 "sort" 9 "testing" 10 "time" 11 12 "github.com/davecgh/go-spew/spew" 13 "github.com/ethereumproject/go-ethereum/common" 14 ) 15 16 var ( 17 cachedbtestAccounts = []Account{ 18 { 19 Address: common.HexToAddress("7ef5a6135f1fd6a02593eedc869c6d41d934aef8"), 20 File: "UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8", 21 EncryptedKey: "{\"address\":\"7ef5a6135f1fd6a02593eedc869c6d41d934aef8\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"1d0839166e7a15b9c1333fc865d69858b22df26815ccf601b28219b6192974e1\",\"cipherparams\":{\"iv\":\"8df6caa7ff1b00c4e871f002cb7921ed\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":8,\"p\":16,\"r\":8,\"salt\":\"e5e6ef3f4ea695f496b643ebd3f75c0aa58ef4070e90c80c5d3fb0241bf1595c\"},\"mac\":\"6d16dfde774845e4585357f24bce530528bc69f4f84e1e22880d34fa45c273e5\"},\"id\":\"950077c7-71e3-4c44-a4a1-143919141ed4\",\"version\":3}", 22 }, 23 { 24 Address: common.HexToAddress("f466859ead1932d743d622cb74fc058882e8648a"), 25 File: "aaa", 26 EncryptedKey: "{\"address\":\"f466859ead1932d743d622cb74fc058882e8648a\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d\",\"cipherparams\":{\"iv\":\"dfd9ee70812add5f4b8f89d0811c9158\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":8,\"p\":16,\"r\":8,\"salt\":\"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1\"},\"mac\":\"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9\"},\"id\":\"472e8b3d-afb6-45b5-8111-72c89895099a\",\"version\":3}", 27 }, 28 { 29 Address: common.HexToAddress("289d485d9771714cce91d3393d764e1311907acc"), 30 File: "zzz", 31 EncryptedKey: "{\"address\":\"289d485d9771714cce91d3393d764e1311907acc\",\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"faf32ca89d286b107f5e6d842802e05263c49b78d46eac74e6109e9a963378ab\",\"cipherparams\":{\"iv\":\"558833eec4a665a8c55608d7d503407d\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":8,\"p\":16,\"r\":8,\"salt\":\"d571fff447ffb24314f9513f5160246f09997b857ac71348b73e785aab40dc04\"},\"mac\":\"21edb85ff7d0dab1767b9bf498f2c3cb7be7609490756bd32300bb213b59effe\"},\"id\":\"3279afcf-55ba-43ff-8997-02dcc46a6525\",\"version\":3}", 32 }, 33 } 34 ) 35 36 func TestCacheInitialReload_CacheDB(t *testing.T) { 37 cache := newCacheDB(cachetestDir) 38 cache.Syncfs2db(time.Now()) 39 defer cache.close() 40 41 accounts := cache.accounts() 42 43 if !reflect.DeepEqual(accounts, cachedbtestAccounts) { 44 t.Errorf("got: %v, want %v", spew.Sdump(accounts), spew.Sdump(cachedbtestAccounts)) 45 } 46 } 47 48 func TestCacheAddDeleteOrder_CacheDB(t *testing.T) { 49 cache := newCacheDB("testdata/no-such-dir") 50 defer cache.close() 51 defer os.RemoveAll("testdata/no-such-dir") 52 53 accounts := []Account{ 54 { 55 Address: common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), 56 File: "-309830980", 57 }, 58 { 59 Address: common.HexToAddress("2cac1adea150210703ba75ed097ddfe24e14f213"), 60 File: "ggg", 61 }, 62 { 63 Address: common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), 64 File: "zzzzzz-the-very-last-one.keyXXX", 65 }, 66 { 67 Address: common.HexToAddress("d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"), 68 File: "SOMETHING.key", 69 }, 70 { 71 Address: common.HexToAddress("7ef5a6135f1fd6a02593eedc869c6d41d934aef8"), 72 File: "UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8", 73 }, 74 { 75 Address: common.HexToAddress("f466859ead1932d743d622cb74fc058882e8648a"), 76 File: "aaa", 77 }, 78 { 79 Address: common.HexToAddress("289d485d9771714cce91d3393d764e1311907acc"), 80 File: "zzz", 81 }, 82 } 83 for _, a := range accounts { 84 cache.add(a) 85 } 86 // Add some of them twice to check that they don't get reinserted. 87 cache.add(accounts[0]) 88 cache.add(accounts[2]) 89 90 // Check that the account list is sorted by filename. 91 wantAccounts := make([]Account, len(accounts)) 92 copy(wantAccounts, accounts) 93 sort.Sort(accountsByFile(wantAccounts)) 94 list := cache.accounts() 95 if !reflect.DeepEqual(list, wantAccounts) { 96 t.Fatalf("got accounts: %s\nwant %s", spew.Sdump(accounts), spew.Sdump(wantAccounts)) 97 } 98 for _, a := range accounts { 99 if !cache.hasAddress(a.Address) { 100 t.Errorf("expected hasAccount(%x) to return true", a.Address) 101 } 102 } 103 if cache.hasAddress(common.HexToAddress("fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e")) { 104 t.Errorf("expected hasAccount(%x) to return false", common.HexToAddress("fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e")) 105 } 106 107 // Delete a few keys from the cache. 108 for i := 0; i < len(accounts); i += 2 { 109 cache.delete(wantAccounts[i]) 110 } 111 cache.delete(Account{Address: common.HexToAddress("fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e"), File: "something"}) 112 113 // Check content again after deletion. 114 wantAccountsAfterDelete := []Account{ 115 wantAccounts[1], 116 wantAccounts[3], 117 wantAccounts[5], 118 } 119 list = cache.accounts() 120 if !reflect.DeepEqual(list, wantAccountsAfterDelete) { 121 t.Fatalf("got accounts after delete: %s\nwant %s", spew.Sdump(list), spew.Sdump(wantAccountsAfterDelete)) 122 } 123 for _, a := range wantAccountsAfterDelete { 124 if !cache.hasAddress(a.Address) { 125 t.Errorf("expected hasAccount(%x) to return true", a.Address) 126 } 127 } 128 if cache.hasAddress(wantAccounts[0].Address) { 129 t.Errorf("expected hasAccount(%x) to return false", wantAccounts[0].Address) 130 } 131 } 132 133 func TestCacheFind_CacheFind(t *testing.T) { 134 dir := filepath.Join("testdata", "dir") 135 cache := newCacheDB(dir) 136 defer cache.close() 137 defer os.RemoveAll(dir) 138 139 accounts := []Account{ 140 { 141 Address: common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), 142 File: "a.key", 143 }, 144 { 145 Address: common.HexToAddress("2cac1adea150210703ba75ed097ddfe24e14f213"), 146 File: "b.key", 147 }, 148 { 149 Address: common.HexToAddress("d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"), 150 File: "c.key", 151 }, 152 { 153 Address: common.HexToAddress("d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"), 154 File: "c2.key", 155 }, 156 } 157 for _, a := range accounts { 158 cache.add(a) 159 } 160 161 if lca := cache.accounts(); len(lca) != len(accounts) { 162 t.Fatalf("wrong number of accounts, got: %v, want: %v", len(lca), len(accounts)) 163 } 164 165 if !reflect.DeepEqual(cache.accounts(), accounts) { 166 t.Fatalf("not matching initial accounts: got %v, want: %v", spew.Sdump(cache.accounts()), spew.Sdump(accounts)) 167 } 168 169 nomatchAccount := Account{ 170 Address: common.HexToAddress("f466859ead1932d743d622cb74fc058882e8648a"), 171 File: filepath.Join(dir, "something"), 172 } 173 tests := []struct { 174 Query Account 175 WantResult Account 176 WantError error 177 }{ 178 // by address 179 {Query: Account{Address: accounts[0].Address}, WantResult: accounts[0]}, 180 // by file 181 {Query: Account{File: accounts[0].File}, WantResult: accounts[0]}, 182 // by basename 183 {Query: Account{File: filepath.Base(accounts[0].File)}, WantResult: accounts[0]}, 184 // by file and address 185 {Query: accounts[0], WantResult: accounts[0]}, 186 // ambiguous address, tie resolved by file 187 {Query: accounts[2], WantResult: accounts[2]}, 188 // ambiguous address error 189 { 190 Query: Account{Address: accounts[2].Address}, 191 WantError: &AmbiguousAddrError{ 192 Addr: accounts[2].Address, 193 Matches: []Account{accounts[2], accounts[3]}, 194 }, 195 }, 196 // no match error 197 {Query: nomatchAccount, WantError: ErrNoMatch}, 198 {Query: Account{File: nomatchAccount.File}, WantError: ErrNoMatch}, 199 {Query: Account{File: filepath.Base(nomatchAccount.File)}, WantError: ErrNoMatch}, 200 {Query: Account{Address: nomatchAccount.Address}, WantError: ErrNoMatch}, 201 } 202 for i, test := range tests { 203 a, err := cache.find(test.Query) 204 if !reflect.DeepEqual(err, test.WantError) { 205 t.Errorf("test %d: error mismatch for query %v\ngot %q\nwant %q", i, test.Query, err, test.WantError) 206 continue 207 } 208 if a != test.WantResult { 209 t.Errorf("test %d: result mismatch for query %v\ngot %v\nwant %v", i, test.Query, a, test.WantResult) 210 continue 211 } 212 } 213 } 214 215 func TestAccountCache_CacheDB_SyncFS2DB(t *testing.T) { 216 // setup temp dir 217 tmpDir, e := ioutil.TempDir("", "cachedb-remover-test") 218 if e != nil { 219 t.Fatalf("create temp dir: %v", e) 220 } 221 defer os.RemoveAll(tmpDir) 222 223 // make manager in temp dir 224 ma, e := NewManager(tmpDir, veryLightScryptN, veryLightScryptP, true) 225 if e != nil { 226 t.Errorf("create manager in temp dir: %v", e) 227 } 228 // test manager has no accounts 229 initAccs := ma.Accounts() 230 if !reflect.DeepEqual(initAccs, []Account{}) { 231 t.Errorf("got %v, want: %v", spew.Sdump(initAccs), spew.Sdump([]Account{})) 232 } 233 // close manager 234 ma.ac.close() 235 ma = nil 236 237 // copy 3 key files to temp dir 238 for _, acc := range cachedbtestAccounts { 239 data, err := ioutil.ReadFile(filepath.Join(cachetestDir, acc.File)) 240 if err != nil { 241 t.Fatal(err) 242 } 243 ff, err := os.Create(filepath.Join(tmpDir, acc.File)) 244 if err != nil { 245 t.Fatal(err) 246 } 247 _, err = ff.Write(data) 248 if err != nil { 249 t.Fatal(err) 250 } 251 ff.Close() 252 } 253 254 // restart manager in temp dir 255 ma, e = NewManager(tmpDir, veryLightScryptN, veryLightScryptP, true) 256 if e != nil { 257 t.Errorf("create manager in temp dir: %v", e) 258 } 259 260 ma.ac.Syncfs2db(time.Now()) 261 262 // test manager has 3 accounts 263 initAccs = ma.Accounts() 264 if !reflect.DeepEqual(initAccs, cachedbtestAccounts) { 265 t.Errorf("got %v, want: %v", spew.Sdump(initAccs), spew.Sdump(cachedbtestAccounts)) 266 } 267 268 // close manager 269 ma.ac.close() 270 ma = nil 271 272 // remove 1 key file from temp dir 273 rmPath := filepath.Join(tmpDir, cachedbtestAccounts[0].File) 274 if e := os.Remove(rmPath); e != nil { 275 t.Fatalf("removing key file: %v", e) 276 } 277 278 // restart manager in temp dir 279 ma, e = NewManager(tmpDir, veryLightScryptN, veryLightScryptP, true) 280 if e != nil { 281 t.Errorf("create manager in temp dir: %v", e) 282 } 283 ma.ac.Syncfs2db(time.Now()) 284 285 // test manager has 2 accounts 286 initAccs = ma.Accounts() 287 if !reflect.DeepEqual(initAccs, cachedbtestAccounts[1:]) { 288 t.Errorf("got %v, want: %v", spew.Sdump(initAccs), spew.Sdump(cachedbtestAccounts[1:])) 289 } 290 ma.ac.close() 291 } 292 293 func TestCacheDBFilePath(t *testing.T) { 294 dir := filepath.Join("testdata", "keystore") 295 dir, _ = filepath.Abs(dir) 296 cache := newCacheDB(dir) 297 defer cache.close() 298 299 accs := cache.accounts() 300 301 for _, a := range accs { 302 if filepath.IsAbs(a.File) { 303 t.Errorf("wanted relative filepath (wanted basename), got: %v", a.File) 304 } 305 } 306 }