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  }