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

     1  // Copyright 2017 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  	"bytes"
    21  	"fmt"
    22  	"io"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"os"
    26  	"path"
    27  	"path/filepath"
    28  	"runtime"
    29  	"strings"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/ethereum/go-ethereum/log"
    34  	swarmapi "github.com/ethereum/go-ethereum/swarm/api/client"
    35  	"github.com/ethereum/go-ethereum/swarm/testutil"
    36  	"github.com/mattn/go-colorable"
    37  )
    38  
    39  func init() {
    40  	log.PrintOrigins(true)
    41  	log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
    42  }
    43  
    44  func TestSwarmUp(t *testing.T) {
    45  	if runtime.GOOS == "windows" {
    46  		t.Skip()
    47  	}
    48  
    49  	initCluster(t)
    50  
    51  	cases := []struct {
    52  		name string
    53  		f    func(t *testing.T)
    54  	}{
    55  		{"NoEncryption", testNoEncryption},
    56  		{"Encrypted", testEncrypted},
    57  		{"RecursiveNoEncryption", testRecursiveNoEncryption},
    58  		{"RecursiveEncrypted", testRecursiveEncrypted},
    59  		{"DefaultPathAll", testDefaultPathAll},
    60  	}
    61  
    62  	for _, tc := range cases {
    63  		t.Run(tc.name, tc.f)
    64  	}
    65  }
    66  
    67  // testNoEncryption tests that running 'swarm up' makes the resulting file
    68  // available from all nodes via the HTTP API
    69  func testNoEncryption(t *testing.T) {
    70  	testDefault(false, t)
    71  }
    72  
    73  // testEncrypted tests that running 'swarm up --encrypted' makes the resulting file
    74  // available from all nodes via the HTTP API
    75  func testEncrypted(t *testing.T) {
    76  	testDefault(true, t)
    77  }
    78  
    79  func testRecursiveNoEncryption(t *testing.T) {
    80  	testRecursive(false, t)
    81  }
    82  
    83  func testRecursiveEncrypted(t *testing.T) {
    84  	testRecursive(true, t)
    85  }
    86  
    87  func testDefault(toEncrypt bool, t *testing.T) {
    88  	tmpFileName := testutil.TempFileWithContent(t, data)
    89  	defer os.Remove(tmpFileName)
    90  
    91  	// write data to file
    92  	hashRegexp := `[a-f\d]{64}`
    93  	flags := []string{
    94  		"--bzzapi", cluster.Nodes[0].URL,
    95  		"up",
    96  		tmpFileName}
    97  	if toEncrypt {
    98  		hashRegexp = `[a-f\d]{128}`
    99  		flags = []string{
   100  			"--bzzapi", cluster.Nodes[0].URL,
   101  			"up",
   102  			"--encrypt",
   103  			tmpFileName}
   104  	}
   105  	// upload the file with 'swarm up' and expect a hash
   106  	log.Info(fmt.Sprintf("uploading file with 'swarm up'"))
   107  	up := runSwarm(t, flags...)
   108  	_, matches := up.ExpectRegexp(hashRegexp)
   109  	up.ExpectExit()
   110  	hash := matches[0]
   111  	log.Info("file uploaded", "hash", hash)
   112  
   113  	// get the file from the HTTP API of each node
   114  	for _, node := range cluster.Nodes {
   115  		log.Info("getting file from node", "node", node.Name)
   116  
   117  		res, err := http.Get(node.URL + "/bzz:/" + hash)
   118  		if err != nil {
   119  			t.Fatal(err)
   120  		}
   121  		defer res.Body.Close()
   122  
   123  		reply, err := ioutil.ReadAll(res.Body)
   124  		if err != nil {
   125  			t.Fatal(err)
   126  		}
   127  		if res.StatusCode != 200 {
   128  			t.Fatalf("expected HTTP status 200, got %s", res.Status)
   129  		}
   130  		if string(reply) != data {
   131  			t.Fatalf("expected HTTP body %q, got %q", data, reply)
   132  		}
   133  		log.Debug("verifying uploaded file using `swarm down`")
   134  		//try to get the content with `swarm down`
   135  		tmpDownload, err := ioutil.TempDir("", "swarm-test")
   136  		tmpDownload = path.Join(tmpDownload, "tmpfile.tmp")
   137  		if err != nil {
   138  			t.Fatal(err)
   139  		}
   140  		defer os.RemoveAll(tmpDownload)
   141  
   142  		bzzLocator := "bzz:/" + hash
   143  		flags = []string{
   144  			"--bzzapi", cluster.Nodes[0].URL,
   145  			"down",
   146  			bzzLocator,
   147  			tmpDownload,
   148  		}
   149  
   150  		down := runSwarm(t, flags...)
   151  		down.ExpectExit()
   152  
   153  		fi, err := os.Stat(tmpDownload)
   154  		if err != nil {
   155  			t.Fatalf("could not stat path: %v", err)
   156  		}
   157  
   158  		switch mode := fi.Mode(); {
   159  		case mode.IsRegular():
   160  			downloadedBytes, err := ioutil.ReadFile(tmpDownload)
   161  			if err != nil {
   162  				t.Fatalf("had an error reading the downloaded file: %v", err)
   163  			}
   164  			if !bytes.Equal(downloadedBytes, bytes.NewBufferString(data).Bytes()) {
   165  				t.Fatalf("retrieved data and posted data not equal!")
   166  			}
   167  
   168  		default:
   169  			t.Fatalf("expected to download regular file, got %s", fi.Mode())
   170  		}
   171  	}
   172  
   173  	timeout := time.Duration(2 * time.Second)
   174  	httpClient := http.Client{
   175  		Timeout: timeout,
   176  	}
   177  
   178  	// try to squeeze a timeout by getting an non-existent hash from each node
   179  	for _, node := range cluster.Nodes {
   180  		_, err := httpClient.Get(node.URL + "/bzz:/1023e8bae0f70be7d7b5f74343088ba408a218254391490c85ae16278e230340")
   181  		// we're speeding up the timeout here since netstore has a 60 seconds timeout on a request
   182  		if err != nil && !strings.Contains(err.Error(), "Client.Timeout exceeded while awaiting headers") {
   183  			t.Fatal(err)
   184  		}
   185  		// this is disabled since it takes 60s due to netstore timeout
   186  		// if res.StatusCode != 404 {
   187  		// 	t.Fatalf("expected HTTP status 404, got %s", res.Status)
   188  		// }
   189  	}
   190  }
   191  
   192  func testRecursive(toEncrypt bool, t *testing.T) {
   193  	tmpUploadDir, err := ioutil.TempDir("", "swarm-test")
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	defer os.RemoveAll(tmpUploadDir)
   198  	// create tmp files
   199  	for _, path := range []string{"tmp1", "tmp2"} {
   200  		if err := ioutil.WriteFile(filepath.Join(tmpUploadDir, path), bytes.NewBufferString(data).Bytes(), 0644); err != nil {
   201  			t.Fatal(err)
   202  		}
   203  	}
   204  
   205  	hashRegexp := `[a-f\d]{64}`
   206  	flags := []string{
   207  		"--bzzapi", cluster.Nodes[0].URL,
   208  		"--recursive",
   209  		"up",
   210  		tmpUploadDir}
   211  	if toEncrypt {
   212  		hashRegexp = `[a-f\d]{128}`
   213  		flags = []string{
   214  			"--bzzapi", cluster.Nodes[0].URL,
   215  			"--recursive",
   216  			"up",
   217  			"--encrypt",
   218  			tmpUploadDir}
   219  	}
   220  	// upload the file with 'swarm up' and expect a hash
   221  	log.Info(fmt.Sprintf("uploading file with 'swarm up'"))
   222  	up := runSwarm(t, flags...)
   223  	_, matches := up.ExpectRegexp(hashRegexp)
   224  	up.ExpectExit()
   225  	hash := matches[0]
   226  	log.Info("dir uploaded", "hash", hash)
   227  
   228  	// get the file from the HTTP API of each node
   229  	for _, node := range cluster.Nodes {
   230  		log.Info("getting file from node", "node", node.Name)
   231  		//try to get the content with `swarm down`
   232  		tmpDownload, err := ioutil.TempDir("", "swarm-test")
   233  		if err != nil {
   234  			t.Fatal(err)
   235  		}
   236  		defer os.RemoveAll(tmpDownload)
   237  		bzzLocator := "bzz:/" + hash
   238  		flagss := []string{
   239  			"--bzzapi", cluster.Nodes[0].URL,
   240  			"down",
   241  			"--recursive",
   242  			bzzLocator,
   243  			tmpDownload,
   244  		}
   245  
   246  		fmt.Println("downloading from swarm with recursive")
   247  		down := runSwarm(t, flagss...)
   248  		down.ExpectExit()
   249  
   250  		files, err := ioutil.ReadDir(tmpDownload)
   251  		for _, v := range files {
   252  			fi, err := os.Stat(path.Join(tmpDownload, v.Name()))
   253  			if err != nil {
   254  				t.Fatalf("got an error: %v", err)
   255  			}
   256  
   257  			switch mode := fi.Mode(); {
   258  			case mode.IsRegular():
   259  				if file, err := swarmapi.Open(path.Join(tmpDownload, v.Name())); err != nil {
   260  					t.Fatalf("encountered an error opening the file returned from the CLI: %v", err)
   261  				} else {
   262  					ff := make([]byte, len(data))
   263  					io.ReadFull(file, ff)
   264  					buf := bytes.NewBufferString(data)
   265  
   266  					if !bytes.Equal(ff, buf.Bytes()) {
   267  						t.Fatalf("retrieved data and posted data not equal!")
   268  					}
   269  				}
   270  			default:
   271  				t.Fatalf("this shouldnt happen")
   272  			}
   273  		}
   274  		if err != nil {
   275  			t.Fatalf("could not list files at: %v", files)
   276  		}
   277  	}
   278  }
   279  
   280  // testDefaultPathAll tests swarm recursive upload with relative and absolute
   281  // default paths and with encryption.
   282  func testDefaultPathAll(t *testing.T) {
   283  	testDefaultPath(false, false, t)
   284  	testDefaultPath(false, true, t)
   285  	testDefaultPath(true, false, t)
   286  	testDefaultPath(true, true, t)
   287  }
   288  
   289  func testDefaultPath(toEncrypt bool, absDefaultPath bool, t *testing.T) {
   290  	tmp, err := ioutil.TempDir("", "swarm-defaultpath-test")
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  	defer os.RemoveAll(tmp)
   295  
   296  	err = ioutil.WriteFile(filepath.Join(tmp, "index.html"), []byte("<h1>Test</h1>"), 0666)
   297  	if err != nil {
   298  		t.Fatal(err)
   299  	}
   300  	err = ioutil.WriteFile(filepath.Join(tmp, "robots.txt"), []byte("Disallow: /"), 0666)
   301  	if err != nil {
   302  		t.Fatal(err)
   303  	}
   304  
   305  	defaultPath := "index.html"
   306  	if absDefaultPath {
   307  		defaultPath = filepath.Join(tmp, defaultPath)
   308  	}
   309  
   310  	args := []string{
   311  		"--bzzapi",
   312  		cluster.Nodes[0].URL,
   313  		"--recursive",
   314  		"--defaultpath",
   315  		defaultPath,
   316  		"up",
   317  		tmp,
   318  	}
   319  	if toEncrypt {
   320  		args = append(args, "--encrypt")
   321  	}
   322  
   323  	up := runSwarm(t, args...)
   324  	hashRegexp := `[a-f\d]{64,128}`
   325  	_, matches := up.ExpectRegexp(hashRegexp)
   326  	up.ExpectExit()
   327  	hash := matches[0]
   328  
   329  	client := swarmapi.NewClient(cluster.Nodes[0].URL)
   330  
   331  	m, isEncrypted, err := client.DownloadManifest(hash)
   332  	if err != nil {
   333  		t.Fatal(err)
   334  	}
   335  
   336  	if toEncrypt != isEncrypted {
   337  		t.Error("downloaded manifest is not encrypted")
   338  	}
   339  
   340  	var found bool
   341  	var entriesCount int
   342  	for _, e := range m.Entries {
   343  		entriesCount++
   344  		if e.Path == "" {
   345  			found = true
   346  		}
   347  	}
   348  
   349  	if !found {
   350  		t.Error("manifest default entry was not found")
   351  	}
   352  
   353  	if entriesCount != 3 {
   354  		t.Errorf("manifest contains %v entries, expected %v", entriesCount, 3)
   355  	}
   356  }