github.com/divan/go-ethereum@v1.8.14-0.20180820134928-1de9ada4016d/swarm/storage/netstore_test.go (about) 1 // Copyright 2018 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 package storage 18 19 import ( 20 "context" 21 "encoding/hex" 22 "errors" 23 "io/ioutil" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/swarm/network" 28 ) 29 30 var ( 31 errUnknown = errors.New("unknown error") 32 ) 33 34 type mockRetrieve struct { 35 requests map[string]int 36 } 37 38 func NewMockRetrieve() *mockRetrieve { 39 return &mockRetrieve{requests: make(map[string]int)} 40 } 41 42 func newDummyChunk(addr Address) *Chunk { 43 chunk := NewChunk(addr, make(chan bool)) 44 chunk.SData = []byte{3, 4, 5} 45 chunk.Size = 3 46 47 return chunk 48 } 49 50 func (m *mockRetrieve) retrieve(ctx context.Context, chunk *Chunk) error { 51 hkey := hex.EncodeToString(chunk.Addr) 52 m.requests[hkey] += 1 53 54 // on second call return error 55 if m.requests[hkey] == 2 { 56 return errUnknown 57 } 58 59 // on third call return data 60 if m.requests[hkey] == 3 { 61 *chunk = *newDummyChunk(chunk.Addr) 62 go func() { 63 time.Sleep(100 * time.Millisecond) 64 close(chunk.ReqC) 65 }() 66 67 return nil 68 } 69 70 return nil 71 } 72 73 func TestNetstoreFailedRequest(t *testing.T) { 74 searchTimeout = 300 * time.Millisecond 75 76 // setup 77 addr := network.RandomAddr() // tested peers peer address 78 79 // temp datadir 80 datadir, err := ioutil.TempDir("", "netstore") 81 if err != nil { 82 t.Fatal(err) 83 } 84 params := NewDefaultLocalStoreParams() 85 params.Init(datadir) 86 params.BaseKey = addr.Over() 87 localStore, err := NewTestLocalStoreForAddr(params) 88 if err != nil { 89 t.Fatal(err) 90 } 91 92 r := NewMockRetrieve() 93 netStore := NewNetStore(localStore, r.retrieve) 94 95 key := Address{} 96 97 // first call is done by the retry on ErrChunkNotFound, no need to do it here 98 // _, err = netStore.Get(key) 99 // if err == nil || err != ErrChunkNotFound { 100 // t.Fatalf("expected to get ErrChunkNotFound, but got: %s", err) 101 // } 102 103 // second call 104 _, err = netStore.Get(context.TODO(), key) 105 if got := r.requests[hex.EncodeToString(key)]; got != 2 { 106 t.Fatalf("expected to have called retrieve two times, but got: %v", got) 107 } 108 if err != errUnknown { 109 t.Fatalf("expected to get an unknown error, but got: %s", err) 110 } 111 112 // third call 113 chunk, err := netStore.Get(context.TODO(), key) 114 if got := r.requests[hex.EncodeToString(key)]; got != 3 { 115 t.Fatalf("expected to have called retrieve three times, but got: %v", got) 116 } 117 if err != nil || chunk == nil { 118 t.Fatalf("expected to get a chunk but got: %v, %s", chunk, err) 119 } 120 if len(chunk.SData) != 3 { 121 t.Fatalf("expected to get a chunk with size 3, but got: %v", chunk.SData) 122 } 123 }