github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/cmd/swarm/global-store/global_store_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "context" 21 "io/ioutil" 22 "net" 23 "net/http" 24 "os" 25 "testing" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/rpc" 30 mockRPC "github.com/ethereum/go-ethereum/swarm/storage/mock/rpc" 31 ) 32 33 // TestHTTP_InMemory tests in-memory global store that exposes 34 // HTTP server. 35 func TestHTTP_InMemory(t *testing.T) { 36 testHTTP(t, true) 37 } 38 39 // TestHTTP_Database tests global store with persisted database 40 // that exposes HTTP server. 41 func TestHTTP_Database(t *testing.T) { 42 dir, err := ioutil.TempDir("", "swarm-global-store-") 43 if err != nil { 44 t.Fatal(err) 45 } 46 defer os.RemoveAll(dir) 47 48 // create a fresh global store 49 testHTTP(t, true, "--dir", dir) 50 51 // check if data saved by the previous global store instance 52 testHTTP(t, false, "--dir", dir) 53 } 54 55 // testWebsocket starts global store binary with HTTP server 56 // and validates that it can store and retrieve data. 57 // If put is false, no data will be stored, only retrieved, 58 // giving the possibility to check if data is present in the 59 // storage directory. 60 func testHTTP(t *testing.T, put bool, args ...string) { 61 addr := findFreeTCPAddress(t) 62 testCmd := runGlobalStore(t, append([]string{"http", "--addr", addr}, args...)...) 63 defer testCmd.Kill() 64 65 client, err := rpc.DialHTTP("http://" + addr) 66 if err != nil { 67 t.Fatal(err) 68 } 69 70 // wait until global store process is started as 71 // rpc.DialHTTP is actually not connecting 72 waitHTTPEndpoint(t, addr) 73 74 store := mockRPC.NewGlobalStore(client) 75 defer store.Close() 76 77 node := store.NewNodeStore(common.HexToAddress("123abc")) 78 79 wantKey := "key" 80 wantValue := "value" 81 82 if put { 83 err = node.Put([]byte(wantKey), []byte(wantValue)) 84 if err != nil { 85 t.Fatal(err) 86 } 87 } 88 89 gotValue, err := node.Get([]byte(wantKey)) 90 if err != nil { 91 t.Fatal(err) 92 } 93 94 if string(gotValue) != wantValue { 95 t.Errorf("got value %s for key %s, want %s", string(gotValue), wantKey, wantValue) 96 } 97 } 98 99 // TestWebsocket_InMemory tests in-memory global store that exposes 100 // WebSocket server. 101 func TestWebsocket_InMemory(t *testing.T) { 102 testWebsocket(t, true) 103 } 104 105 // TestWebsocket_Database tests global store with persisted database 106 // that exposes HTTP server. 107 func TestWebsocket_Database(t *testing.T) { 108 dir, err := ioutil.TempDir("", "swarm-global-store-") 109 if err != nil { 110 t.Fatal(err) 111 } 112 defer os.RemoveAll(dir) 113 114 // create a fresh global store 115 testWebsocket(t, true, "--dir", dir) 116 117 // check if data saved by the previous global store instance 118 testWebsocket(t, false, "--dir", dir) 119 } 120 121 // testWebsocket starts global store binary with WebSocket server 122 // and validates that it can store and retrieve data. 123 // If put is false, no data will be stored, only retrieved, 124 // giving the possibility to check if data is present in the 125 // storage directory. 126 func testWebsocket(t *testing.T, put bool, args ...string) { 127 addr := findFreeTCPAddress(t) 128 testCmd := runGlobalStore(t, append([]string{"ws", "--addr", addr}, args...)...) 129 defer testCmd.Kill() 130 131 client := websocketClient(t, addr) 132 133 store := mockRPC.NewGlobalStore(client) 134 defer store.Close() 135 136 node := store.NewNodeStore(common.HexToAddress("123abc")) 137 138 wantKey := "key" 139 wantValue := "value" 140 141 if put { 142 err := node.Put([]byte(wantKey), []byte(wantValue)) 143 if err != nil { 144 t.Fatal(err) 145 } 146 } 147 148 gotValue, err := node.Get([]byte(wantKey)) 149 if err != nil { 150 t.Fatal(err) 151 } 152 153 if string(gotValue) != wantValue { 154 t.Errorf("got value %s for key %s, want %s", string(gotValue), wantKey, wantValue) 155 } 156 } 157 158 // findFreeTCPAddress returns a local address (IP:Port) to which 159 // global store can listen on. 160 func findFreeTCPAddress(t *testing.T) (addr string) { 161 t.Helper() 162 163 listener, err := net.Listen("tcp", "") 164 if err != nil { 165 t.Fatal(err) 166 } 167 defer listener.Close() 168 169 return listener.Addr().String() 170 } 171 172 // websocketClient waits until global store process is started 173 // and returns rpc client. 174 func websocketClient(t *testing.T, addr string) (client *rpc.Client) { 175 t.Helper() 176 177 var err error 178 for i := 0; i < 1000; i++ { 179 client, err = rpc.DialWebsocket(context.Background(), "ws://"+addr, "") 180 if err == nil { 181 break 182 } 183 time.Sleep(10 * time.Millisecond) 184 } 185 if err != nil { 186 t.Fatal(err) 187 } 188 return client 189 } 190 191 // waitHTTPEndpoint retries http requests to a provided 192 // address until the connection is established. 193 func waitHTTPEndpoint(t *testing.T, addr string) { 194 t.Helper() 195 196 var err error 197 for i := 0; i < 1000; i++ { 198 _, err = http.Get("http://" + addr) 199 if err == nil { 200 break 201 } 202 time.Sleep(10 * time.Millisecond) 203 } 204 if err != nil { 205 t.Fatal(err) 206 } 207 }