github.com/codingfuture/orig-energi3@v0.8.4/swarm/swarm_test.go (about)

     1  // Copyright 2018 The Energi Core Authors
     2  // Copyright 2018 The go-ethereum Authors
     3  // This file is part of the Energi Core library.
     4  //
     5  // The Energi Core library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser 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  // The Energi Core library 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 Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package swarm
    19  
    20  import (
    21  	"context"
    22  	"encoding/hex"
    23  	"io/ioutil"
    24  	"math/rand"
    25  	"os"
    26  	"path"
    27  	"runtime"
    28  	"strings"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/crypto"
    34  	"github.com/ethereum/go-ethereum/rpc"
    35  	"github.com/ethereum/go-ethereum/swarm/api"
    36  )
    37  
    38  // TestNewSwarm validates Swarm fields in repsect to the provided configuration.
    39  func TestNewSwarm(t *testing.T) {
    40  	dir, err := ioutil.TempDir("", "swarm")
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	defer os.RemoveAll(dir)
    45  
    46  	// a simple rpc endpoint for testing dialing
    47  	ipcEndpoint := path.Join(dir, "TestSwarm.ipc")
    48  
    49  	// windows namedpipes are not on filesystem but on NPFS
    50  	if runtime.GOOS == "windows" {
    51  		b := make([]byte, 8)
    52  		rand.Read(b)
    53  		ipcEndpoint = `\\.\pipe\TestSwarm-` + hex.EncodeToString(b)
    54  	}
    55  
    56  	_, server, err := rpc.StartIPCEndpoint(ipcEndpoint, nil)
    57  	if err != nil {
    58  		t.Error(err)
    59  	}
    60  	defer server.Stop()
    61  
    62  	for _, tc := range []struct {
    63  		name      string
    64  		configure func(*api.Config)
    65  		check     func(*testing.T, *Swarm, *api.Config)
    66  	}{
    67  		{
    68  			name:      "defaults",
    69  			configure: nil,
    70  			check: func(t *testing.T, s *Swarm, config *api.Config) {
    71  				if s.config != config {
    72  					t.Error("config is not the same object")
    73  				}
    74  				if s.backend != nil {
    75  					t.Error("backend is not nil")
    76  				}
    77  				if s.privateKey == nil {
    78  					t.Error("private key is not set")
    79  				}
    80  				if !s.config.HiveParams.Discovery {
    81  					t.Error("config.HiveParams.Discovery is false, must be true regardless the configuration")
    82  				}
    83  				if s.dns != nil {
    84  					t.Error("dns initialized, but it should not be")
    85  				}
    86  				if s.netStore == nil {
    87  					t.Error("netStore not initialized")
    88  				}
    89  				if s.streamer == nil {
    90  					t.Error("streamer not initialized")
    91  				}
    92  				if s.fileStore == nil {
    93  					t.Error("fileStore not initialized")
    94  				}
    95  				if s.bzz == nil {
    96  					t.Error("bzz not initialized")
    97  				}
    98  				if s.ps == nil {
    99  					t.Error("pss not initialized")
   100  				}
   101  				if s.api == nil {
   102  					t.Error("api not initialized")
   103  				}
   104  				if s.sfs == nil {
   105  					t.Error("swarm filesystem not initialized")
   106  				}
   107  			},
   108  		},
   109  		{
   110  			name: "with swap",
   111  			configure: func(config *api.Config) {
   112  				config.SwapAPI = ipcEndpoint
   113  				config.SwapEnabled = true
   114  			},
   115  			check: func(t *testing.T, s *Swarm, _ *api.Config) {
   116  				if s.backend == nil {
   117  					t.Error("backend is nil")
   118  				}
   119  			},
   120  		},
   121  		{
   122  			name: "with swap disabled",
   123  			configure: func(config *api.Config) {
   124  				config.SwapAPI = ipcEndpoint
   125  				config.SwapEnabled = false
   126  			},
   127  			check: func(t *testing.T, s *Swarm, _ *api.Config) {
   128  				if s.backend != nil {
   129  					t.Error("backend is not nil")
   130  				}
   131  			},
   132  		},
   133  		{
   134  			name: "with swap enabled and api endpoint blank",
   135  			configure: func(config *api.Config) {
   136  				config.SwapAPI = ""
   137  				config.SwapEnabled = true
   138  			},
   139  			check: func(t *testing.T, s *Swarm, _ *api.Config) {
   140  				if s.backend != nil {
   141  					t.Error("backend is not nil")
   142  				}
   143  			},
   144  		},
   145  		{
   146  			name: "ens",
   147  			configure: func(config *api.Config) {
   148  				config.EnsAPIs = []string{
   149  					"http://127.0.0.1:8888",
   150  				}
   151  			},
   152  			check: func(t *testing.T, s *Swarm, _ *api.Config) {
   153  				if s.dns == nil {
   154  					t.Error("dns is not initialized")
   155  				}
   156  			},
   157  		},
   158  	} {
   159  		t.Run(tc.name, func(t *testing.T) {
   160  			config := api.NewConfig()
   161  
   162  			dir, err := ioutil.TempDir("", "swarm")
   163  			if err != nil {
   164  				t.Fatal(err)
   165  			}
   166  			defer os.RemoveAll(dir)
   167  
   168  			config.Path = dir
   169  
   170  			privkey, err := crypto.GenerateKey()
   171  			if err != nil {
   172  				t.Fatal(err)
   173  			}
   174  
   175  			config.Init(privkey)
   176  
   177  			if tc.configure != nil {
   178  				tc.configure(config)
   179  			}
   180  
   181  			s, err := NewSwarm(config, nil)
   182  			if err != nil {
   183  				t.Fatal(err)
   184  			}
   185  
   186  			if tc.check != nil {
   187  				tc.check(t, s, config)
   188  			}
   189  		})
   190  	}
   191  }
   192  
   193  func TestParseEnsAPIAddress(t *testing.T) {
   194  	for _, x := range []struct {
   195  		description string
   196  		value       string
   197  		tld         string
   198  		endpoint    string
   199  		addr        common.Address
   200  	}{
   201  		{
   202  			description: "IPC endpoint",
   203  			value:       "/data/testnet/geth.ipc",
   204  			endpoint:    "/data/testnet/geth.ipc",
   205  		},
   206  		{
   207  			description: "HTTP endpoint",
   208  			value:       "http://127.0.0.1:1234",
   209  			endpoint:    "http://127.0.0.1:1234",
   210  		},
   211  		{
   212  			description: "WS endpoint",
   213  			value:       "ws://127.0.0.1:1234",
   214  			endpoint:    "ws://127.0.0.1:1234",
   215  		},
   216  		{
   217  			description: "IPC Endpoint and TLD",
   218  			value:       "test:/data/testnet/geth.ipc",
   219  			endpoint:    "/data/testnet/geth.ipc",
   220  			tld:         "test",
   221  		},
   222  		{
   223  			description: "HTTP endpoint and TLD",
   224  			value:       "test:http://127.0.0.1:1234",
   225  			endpoint:    "http://127.0.0.1:1234",
   226  			tld:         "test",
   227  		},
   228  		{
   229  			description: "WS endpoint and TLD",
   230  			value:       "test:ws://127.0.0.1:1234",
   231  			endpoint:    "ws://127.0.0.1:1234",
   232  			tld:         "test",
   233  		},
   234  		{
   235  			description: "IPC Endpoint and contract address",
   236  			value:       "314159265dD8dbb310642f98f50C066173C1259b@/data/testnet/geth.ipc",
   237  			endpoint:    "/data/testnet/geth.ipc",
   238  			addr:        common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"),
   239  		},
   240  		{
   241  			description: "HTTP endpoint and contract address",
   242  			value:       "314159265dD8dbb310642f98f50C066173C1259b@http://127.0.0.1:1234",
   243  			endpoint:    "http://127.0.0.1:1234",
   244  			addr:        common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"),
   245  		},
   246  		{
   247  			description: "WS endpoint and contract address",
   248  			value:       "314159265dD8dbb310642f98f50C066173C1259b@ws://127.0.0.1:1234",
   249  			endpoint:    "ws://127.0.0.1:1234",
   250  			addr:        common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"),
   251  		},
   252  		{
   253  			description: "IPC Endpoint, TLD and contract address",
   254  			value:       "test:314159265dD8dbb310642f98f50C066173C1259b@/data/testnet/geth.ipc",
   255  			endpoint:    "/data/testnet/geth.ipc",
   256  			addr:        common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"),
   257  			tld:         "test",
   258  		},
   259  		{
   260  			description: "HTTP endpoint, TLD and contract address",
   261  			value:       "eth:314159265dD8dbb310642f98f50C066173C1259b@http://127.0.0.1:1234",
   262  			endpoint:    "http://127.0.0.1:1234",
   263  			addr:        common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"),
   264  			tld:         "eth",
   265  		},
   266  		{
   267  			description: "WS endpoint, TLD and contract address",
   268  			value:       "eth:314159265dD8dbb310642f98f50C066173C1259b@ws://127.0.0.1:1234",
   269  			endpoint:    "ws://127.0.0.1:1234",
   270  			addr:        common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"),
   271  			tld:         "eth",
   272  		},
   273  	} {
   274  		t.Run(x.description, func(t *testing.T) {
   275  			tld, endpoint, addr := parseEnsAPIAddress(x.value)
   276  			if endpoint != x.endpoint {
   277  				t.Errorf("expected Endpoint %q, got %q", x.endpoint, endpoint)
   278  			}
   279  			if addr != x.addr {
   280  				t.Errorf("expected ContractAddress %q, got %q", x.addr.String(), addr.String())
   281  			}
   282  			if tld != x.tld {
   283  				t.Errorf("expected TLD %q, got %q", x.tld, tld)
   284  			}
   285  		})
   286  	}
   287  }
   288  
   289  // TestLocalStoreAndRetrieve runs multiple tests where different size files are uploaded
   290  // to a single Swarm instance using API Store and checked against the content returned
   291  // by API Retrieve function.
   292  //
   293  // This test is intended to validate functionality of chunker store and join functions
   294  // and their intergartion into Swarm, without comparing results with ones produced by
   295  // another chunker implementation, as it is done in swarm/storage tests.
   296  func TestLocalStoreAndRetrieve(t *testing.T) {
   297  	config := api.NewConfig()
   298  
   299  	dir, err := ioutil.TempDir("", "node")
   300  	if err != nil {
   301  		t.Fatal(err)
   302  	}
   303  	defer os.RemoveAll(dir)
   304  
   305  	config.Path = dir
   306  
   307  	privkey, err := crypto.GenerateKey()
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	config.Init(privkey)
   313  
   314  	swarm, err := NewSwarm(config, nil)
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  
   319  	// by default, test only the lonely chunk cases
   320  	sizes := []int{1, 60, 4097, 524288 + 1, 7*524288 + 1}
   321  
   322  	if *longrunning {
   323  		// test broader set of cases if -longruning flag is set
   324  		sizes = append(sizes, 83, 179, 253, 1024, 4095, 4096, 8191, 8192, 8193, 12287, 12288, 12289, 123456, 2345678, 67298391, 524288, 524288+4096, 524288+4097, 7*524288, 7*524288+4096, 7*524288+4097, 128*524288+1, 128*524288, 128*524288+4096, 128*524288+4097, 816778334)
   325  	}
   326  	for _, n := range sizes {
   327  		testLocalStoreAndRetrieve(t, swarm, n, true)
   328  		testLocalStoreAndRetrieve(t, swarm, n, false)
   329  	}
   330  }
   331  
   332  // testLocalStoreAndRetrieve is using a single Swarm instance, to upload
   333  // a file of length n with optional random data using API Store function,
   334  // and checks the output of API Retrieve function on the same instance.
   335  // This is a regression test for issue
   336  // https://github.com/ethersphere/go-ethereum/issues/639
   337  // where pyramid chunker did not split correctly files with lengths that
   338  // are edge cases for chunk and tree parameters, depending whether there
   339  // is a tree chunk with only one data chunk and how the compress functionality
   340  // changed the tree.
   341  func testLocalStoreAndRetrieve(t *testing.T, swarm *Swarm, n int, randomData bool) {
   342  	slice := make([]byte, n)
   343  	if randomData {
   344  		rand.Seed(time.Now().UnixNano())
   345  		rand.Read(slice)
   346  	}
   347  	dataPut := string(slice)
   348  
   349  	ctx := context.TODO()
   350  	k, wait, err := swarm.api.Store(ctx, strings.NewReader(dataPut), int64(len(dataPut)), false)
   351  	if err != nil {
   352  		t.Fatal(err)
   353  	}
   354  	if wait != nil {
   355  		err = wait(ctx)
   356  		if err != nil {
   357  			t.Fatal(err)
   358  		}
   359  	}
   360  
   361  	r, _ := swarm.api.Retrieve(context.TODO(), k)
   362  
   363  	d, err := ioutil.ReadAll(r)
   364  	if err != nil {
   365  		t.Fatal(err)
   366  	}
   367  	dataGet := string(d)
   368  
   369  	if len(dataPut) != len(dataGet) {
   370  		t.Fatalf("data not matched: length expected %v, got %v", len(dataPut), len(dataGet))
   371  	} else {
   372  		if dataPut != dataGet {
   373  			t.Fatal("data not matched")
   374  		}
   375  	}
   376  }