github.com/codingfuture/orig-energi3@v0.8.4/cmd/swarm/global-store/global_store_test.go (about)

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