github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/api/client/client_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:43</date>
    10  //</624450111413424128>
    11  
    12  
    13  package client
    14  
    15  import (
    16  	"bytes"
    17  	"io/ioutil"
    18  	"os"
    19  	"path/filepath"
    20  	"reflect"
    21  	"sort"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/swarm/storage"
    25  	"github.com/ethereum/go-ethereum/swarm/storage/feed/lookup"
    26  
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/crypto"
    29  	"github.com/ethereum/go-ethereum/swarm/api"
    30  	swarmhttp "github.com/ethereum/go-ethereum/swarm/api/http"
    31  	"github.com/ethereum/go-ethereum/swarm/storage/feed"
    32  )
    33  
    34  func serverFunc(api *api.API) swarmhttp.TestServer {
    35  	return swarmhttp.NewServer(api, "")
    36  }
    37  
    38  //测试客户端上传下载原始测试上传和下载原始数据到Swarm
    39  func TestClientUploadDownloadRaw(t *testing.T) {
    40  	testClientUploadDownloadRaw(false, t)
    41  }
    42  func TestClientUploadDownloadRawEncrypted(t *testing.T) {
    43  	testClientUploadDownloadRaw(true, t)
    44  }
    45  
    46  func testClientUploadDownloadRaw(toEncrypt bool, t *testing.T) {
    47  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
    48  	defer srv.Close()
    49  
    50  	client := NewClient(srv.URL)
    51  
    52  //上传一些原始数据
    53  	data := []byte("foo123")
    54  	hash, err := client.UploadRaw(bytes.NewReader(data), int64(len(data)), toEncrypt)
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  //检查我们是否可以下载相同的数据
    60  	res, isEncrypted, err := client.DownloadRaw(hash)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	if isEncrypted != toEncrypt {
    65  		t.Fatalf("Expected encyption status %v got %v", toEncrypt, isEncrypted)
    66  	}
    67  	defer res.Close()
    68  	gotData, err := ioutil.ReadAll(res)
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	if !bytes.Equal(gotData, data) {
    73  		t.Fatalf("expected downloaded data to be %q, got %q", data, gotData)
    74  	}
    75  }
    76  
    77  //测试客户端上传下载文件测试上传和下载文件到Swarm
    78  //清单
    79  func TestClientUploadDownloadFiles(t *testing.T) {
    80  	testClientUploadDownloadFiles(false, t)
    81  }
    82  
    83  func TestClientUploadDownloadFilesEncrypted(t *testing.T) {
    84  	testClientUploadDownloadFiles(true, t)
    85  }
    86  
    87  func testClientUploadDownloadFiles(toEncrypt bool, t *testing.T) {
    88  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
    89  	defer srv.Close()
    90  
    91  	client := NewClient(srv.URL)
    92  	upload := func(manifest, path string, data []byte) string {
    93  		file := &File{
    94  			ReadCloser: ioutil.NopCloser(bytes.NewReader(data)),
    95  			ManifestEntry: api.ManifestEntry{
    96  				Path:        path,
    97  				ContentType: "text/plain",
    98  				Size:        int64(len(data)),
    99  			},
   100  		}
   101  		hash, err := client.Upload(file, manifest, toEncrypt)
   102  		if err != nil {
   103  			t.Fatal(err)
   104  		}
   105  		return hash
   106  	}
   107  	checkDownload := func(manifest, path string, expected []byte) {
   108  		file, err := client.Download(manifest, path)
   109  		if err != nil {
   110  			t.Fatal(err)
   111  		}
   112  		defer file.Close()
   113  		if file.Size != int64(len(expected)) {
   114  			t.Fatalf("expected downloaded file to be %d bytes, got %d", len(expected), file.Size)
   115  		}
   116  		if file.ContentType != "text/plain" {
   117  			t.Fatalf("expected downloaded file to have type %q, got %q", "text/plain", file.ContentType)
   118  		}
   119  		data, err := ioutil.ReadAll(file)
   120  		if err != nil {
   121  			t.Fatal(err)
   122  		}
   123  		if !bytes.Equal(data, expected) {
   124  			t.Fatalf("expected downloaded data to be %q, got %q", expected, data)
   125  		}
   126  	}
   127  
   128  //将文件上载到清单的根目录
   129  	rootData := []byte("some-data")
   130  	rootHash := upload("", "", rootData)
   131  
   132  //检查我们是否可以下载根文件
   133  	checkDownload(rootHash, "", rootData)
   134  
   135  //将另一个文件上载到同一清单
   136  	otherData := []byte("some-other-data")
   137  	newHash := upload(rootHash, "some/other/path", otherData)
   138  
   139  //检查我们可以从新清单下载这两个文件
   140  	checkDownload(newHash, "", rootData)
   141  	checkDownload(newHash, "some/other/path", otherData)
   142  
   143  //用不同的数据替换根文件
   144  	newHash = upload(newHash, "", otherData)
   145  
   146  //检查两个文件是否都有其他数据
   147  	checkDownload(newHash, "", otherData)
   148  	checkDownload(newHash, "some/other/path", otherData)
   149  }
   150  
   151  var testDirFiles = []string{
   152  	"file1.txt",
   153  	"file2.txt",
   154  	"dir1/file3.txt",
   155  	"dir1/file4.txt",
   156  	"dir2/file5.txt",
   157  	"dir2/dir3/file6.txt",
   158  	"dir2/dir4/file7.txt",
   159  	"dir2/dir4/file8.txt",
   160  }
   161  
   162  func newTestDirectory(t *testing.T) string {
   163  	dir, err := ioutil.TempDir("", "swarm-client-test")
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  
   168  	for _, file := range testDirFiles {
   169  		path := filepath.Join(dir, file)
   170  		if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
   171  			os.RemoveAll(dir)
   172  			t.Fatalf("error creating dir for %s: %s", path, err)
   173  		}
   174  		if err := ioutil.WriteFile(path, []byte(file), 0644); err != nil {
   175  			os.RemoveAll(dir)
   176  			t.Fatalf("error writing file %s: %s", path, err)
   177  		}
   178  	}
   179  
   180  	return dir
   181  }
   182  
   183  //测试客户端上载下载目录测试上载和下载
   184  //Swarm清单的文件目录
   185  func TestClientUploadDownloadDirectory(t *testing.T) {
   186  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
   187  	defer srv.Close()
   188  
   189  	dir := newTestDirectory(t)
   190  	defer os.RemoveAll(dir)
   191  
   192  //上传目录
   193  	client := NewClient(srv.URL)
   194  	defaultPath := testDirFiles[0]
   195  	hash, err := client.UploadDirectory(dir, defaultPath, "", false)
   196  	if err != nil {
   197  		t.Fatalf("error uploading directory: %s", err)
   198  	}
   199  
   200  //检查我们是否可以下载单独的文件
   201  	checkDownloadFile := func(path string, expected []byte) {
   202  		file, err := client.Download(hash, path)
   203  		if err != nil {
   204  			t.Fatal(err)
   205  		}
   206  		defer file.Close()
   207  		data, err := ioutil.ReadAll(file)
   208  		if err != nil {
   209  			t.Fatal(err)
   210  		}
   211  		if !bytes.Equal(data, expected) {
   212  			t.Fatalf("expected data to be %q, got %q", expected, data)
   213  		}
   214  	}
   215  	for _, file := range testDirFiles {
   216  		checkDownloadFile(file, []byte(file))
   217  	}
   218  
   219  //检查我们是否可以下载默认路径
   220  	checkDownloadFile("", []byte(testDirFiles[0]))
   221  
   222  //检查我们可以下载目录
   223  	tmp, err := ioutil.TempDir("", "swarm-client-test")
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	defer os.RemoveAll(tmp)
   228  	if err := client.DownloadDirectory(hash, "", tmp, ""); err != nil {
   229  		t.Fatal(err)
   230  	}
   231  	for _, file := range testDirFiles {
   232  		data, err := ioutil.ReadFile(filepath.Join(tmp, file))
   233  		if err != nil {
   234  			t.Fatal(err)
   235  		}
   236  		if !bytes.Equal(data, []byte(file)) {
   237  			t.Fatalf("expected data to be %q, got %q", file, data)
   238  		}
   239  	}
   240  }
   241  
   242  //testclientfilelist在swarm清单中列出文件的测试
   243  func TestClientFileList(t *testing.T) {
   244  	testClientFileList(false, t)
   245  }
   246  
   247  func TestClientFileListEncrypted(t *testing.T) {
   248  	testClientFileList(true, t)
   249  }
   250  
   251  func testClientFileList(toEncrypt bool, t *testing.T) {
   252  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
   253  	defer srv.Close()
   254  
   255  	dir := newTestDirectory(t)
   256  	defer os.RemoveAll(dir)
   257  
   258  	client := NewClient(srv.URL)
   259  	hash, err := client.UploadDirectory(dir, "", "", toEncrypt)
   260  	if err != nil {
   261  		t.Fatalf("error uploading directory: %s", err)
   262  	}
   263  
   264  	ls := func(prefix string) []string {
   265  		list, err := client.List(hash, prefix, "")
   266  		if err != nil {
   267  			t.Fatal(err)
   268  		}
   269  		paths := make([]string, 0, len(list.CommonPrefixes)+len(list.Entries))
   270  		paths = append(paths, list.CommonPrefixes...)
   271  		for _, entry := range list.Entries {
   272  			paths = append(paths, entry.Path)
   273  		}
   274  		sort.Strings(paths)
   275  		return paths
   276  	}
   277  
   278  	tests := map[string][]string{
   279  		"":                    {"dir1/", "dir2/", "file1.txt", "file2.txt"},
   280  		"file":                {"file1.txt", "file2.txt"},
   281  		"file1":               {"file1.txt"},
   282  		"file2.txt":           {"file2.txt"},
   283  		"file12":              {},
   284  		"dir":                 {"dir1/", "dir2/"},
   285  		"dir1":                {"dir1/"},
   286  		"dir1/":               {"dir1/file3.txt", "dir1/file4.txt"},
   287  		"dir1/file":           {"dir1/file3.txt", "dir1/file4.txt"},
   288  		"dir1/file3.txt":      {"dir1/file3.txt"},
   289  		"dir1/file34":         {},
   290  		"dir2/":               {"dir2/dir3/", "dir2/dir4/", "dir2/file5.txt"},
   291  		"dir2/file":           {"dir2/file5.txt"},
   292  		"dir2/dir":            {"dir2/dir3/", "dir2/dir4/"},
   293  		"dir2/dir3/":          {"dir2/dir3/file6.txt"},
   294  		"dir2/dir4/":          {"dir2/dir4/file7.txt", "dir2/dir4/file8.txt"},
   295  		"dir2/dir4/file":      {"dir2/dir4/file7.txt", "dir2/dir4/file8.txt"},
   296  		"dir2/dir4/file7.txt": {"dir2/dir4/file7.txt"},
   297  		"dir2/dir4/file78":    {},
   298  	}
   299  	for prefix, expected := range tests {
   300  		actual := ls(prefix)
   301  		if !reflect.DeepEqual(actual, expected) {
   302  			t.Fatalf("expected prefix %q to return %v, got %v", prefix, expected, actual)
   303  		}
   304  	}
   305  }
   306  
   307  //testclientmultipartupload测试使用多部分将文件上载到swarm
   308  //上传
   309  func TestClientMultipartUpload(t *testing.T) {
   310  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
   311  	defer srv.Close()
   312  
   313  //定义上载程序,该上载程序使用某些数据上载testdir文件
   314  	data := []byte("some-data")
   315  	uploader := UploaderFunc(func(upload UploadFn) error {
   316  		for _, name := range testDirFiles {
   317  			file := &File{
   318  				ReadCloser: ioutil.NopCloser(bytes.NewReader(data)),
   319  				ManifestEntry: api.ManifestEntry{
   320  					Path:        name,
   321  					ContentType: "text/plain",
   322  					Size:        int64(len(data)),
   323  				},
   324  			}
   325  			if err := upload(file); err != nil {
   326  				return err
   327  			}
   328  		}
   329  		return nil
   330  	})
   331  
   332  //以多部分上载方式上载文件
   333  	client := NewClient(srv.URL)
   334  	hash, err := client.MultipartUpload("", uploader)
   335  	if err != nil {
   336  		t.Fatal(err)
   337  	}
   338  
   339  //检查我们是否可以下载单独的文件
   340  	checkDownloadFile := func(path string) {
   341  		file, err := client.Download(hash, path)
   342  		if err != nil {
   343  			t.Fatal(err)
   344  		}
   345  		defer file.Close()
   346  		gotData, err := ioutil.ReadAll(file)
   347  		if err != nil {
   348  			t.Fatal(err)
   349  		}
   350  		if !bytes.Equal(gotData, data) {
   351  			t.Fatalf("expected data to be %q, got %q", data, gotData)
   352  		}
   353  	}
   354  	for _, file := range testDirFiles {
   355  		checkDownloadFile(file)
   356  	}
   357  }
   358  
   359  func newTestSigner() (*feed.GenericSigner, error) {
   360  	privKey, err := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
   361  	if err != nil {
   362  		return nil, err
   363  	}
   364  	return feed.NewGenericSigner(privKey), nil
   365  }
   366  
   367  //使用bzz://scheme测试源更新的透明解析
   368  //
   369  //首先将数据上传到bzz:,并将swarm散列存储到feed更新中的结果清单中。
   370  //这有效地使用提要来存储指向内容的指针,而不是内容本身。
   371  //使用swarm散列检索更新应返回直接指向数据的清单。
   372  //对散列的原始检索应该返回数据
   373  func TestClientBzzWithFeed(t *testing.T) {
   374  
   375  	signer, _ := newTestSigner()
   376  
   377  //初始化Swarm测试服务器
   378  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
   379  	swarmClient := NewClient(srv.URL)
   380  	defer srv.Close()
   381  
   382  //为我们的测试收集一些数据:
   383  	dataBytes := []byte(`
   384  //
   385  //创建一些我们的清单将指向的数据。数据可能非常大,不适合feed更新。
   386  //因此,我们要做的是将其上传到swarm bzz/,并获取指向它的**清单哈希**:
   387  //
   388  //清单哈希-->数据
   389  //
   390  //然后,我们将该**清单哈希**存储到一个swarm feed更新中。一旦我们这样做了,
   391  //我们可以使用bzz://feed manifest散列中的**feed manifest散列,方法是:bzz://feed manifest散列。
   392  //
   393  //源清单哈希——>清单哈希——>数据
   394  //
   395  //假设我们可以在任何时候用一个新的**清单哈希**更新提要,但是**提要清单哈希**。
   396  //保持不变,我们有效地创建了一个固定地址来更改内容。(掌声)
   397  //
   398  //源清单哈希(相同)->清单哈希(2)->数据(2)
   399  //
   400  	`)
   401  
   402  //从包含上述数据的内存中创建虚拟文件
   403  	f := &File{
   404  		ReadCloser: ioutil.NopCloser(bytes.NewReader(dataBytes)),
   405  		ManifestEntry: api.ManifestEntry{
   406  			ContentType: "text/plain",
   407  			Mode:        0660,
   408  			Size:        int64(len(dataBytes)),
   409  		},
   410  	}
   411  
   412  //将数据上载到bzz://并检索内容寻址清单哈希,十六进制编码。
   413  	manifestAddressHex, err := swarmClient.Upload(f, "", false)
   414  	if err != nil {
   415  		t.Fatalf("Error creating manifest: %s", err)
   416  	}
   417  
   418  //将十六进制编码的清单哈希转换为32字节的切片
   419  	manifestAddress := common.FromHex(manifestAddressHex)
   420  
   421  	if len(manifestAddress) != storage.AddressLength {
   422  		t.Fatalf("Something went wrong. Got a hash of an unexpected length. Expected %d bytes. Got %d", storage.AddressLength, len(manifestAddress))
   423  	}
   424  
   425  //现在创建一个**源清单**。为此,我们需要一个主题:
   426  	topic, _ := feed.NewTopic("interesting topic indeed", nil)
   427  
   428  //生成源请求以更新数据
   429  	request := feed.NewFirstRequest(topic)
   430  
   431  //将清单的32字节地址放入源更新中
   432  	request.SetData(manifestAddress)
   433  
   434  //签署更新
   435  	if err := request.Sign(signer); err != nil {
   436  		t.Fatalf("Error signing update: %s", err)
   437  	}
   438  
   439  //发布更新,同时请求创建一个**源清单**。
   440  	feedManifestAddressHex, err := swarmClient.CreateFeedWithManifest(request)
   441  	if err != nil {
   442  		t.Fatalf("Error creating feed manifest: %s", err)
   443  	}
   444  
   445  //检查我们是否收到了预期的确切**源清单**。
   446  //给定主题和用户对更新进行签名:
   447  	correctFeedManifestAddrHex := "747c402e5b9dc715a25a4393147512167bab018a007fad7cdcd9adc7fce1ced2"
   448  	if feedManifestAddressHex != correctFeedManifestAddrHex {
   449  		t.Fatalf("Response feed manifest mismatch, expected '%s', got '%s'", correctFeedManifestAddrHex, feedManifestAddressHex)
   450  	}
   451  
   452  //检查我们在尝试获取包含组合清单的源更新时是否出现未找到错误
   453  	_, err = swarmClient.QueryFeed(nil, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
   454  	if err != ErrNoFeedUpdatesFound {
   455  		t.Fatalf("Expected to receive ErrNoFeedUpdatesFound error. Got: %s", err)
   456  	}
   457  
   458  //如果我们直接查询feed,我们应该得到**manifest hash**返回:
   459  	reader, err := swarmClient.QueryFeed(nil, correctFeedManifestAddrHex)
   460  	if err != nil {
   461  		t.Fatalf("Error retrieving feed updates: %s", err)
   462  	}
   463  	defer reader.Close()
   464  	gotData, err := ioutil.ReadAll(reader)
   465  	if err != nil {
   466  		t.Fatal(err)
   467  	}
   468  
   469  //检查是否确实检索到了**清单哈希**。
   470  	if !bytes.Equal(manifestAddress, gotData) {
   471  		t.Fatalf("Expected: %v, got %v", manifestAddress, gotData)
   472  	}
   473  
   474  //现在,我们正在寻找的最后一个测试是:使用bzz://<feed manifest>并且应该解析所有清单
   475  //直接返回原始数据:
   476  	f, err = swarmClient.Download(feedManifestAddressHex, "")
   477  	if err != nil {
   478  		t.Fatal(err)
   479  	}
   480  	gotData, err = ioutil.ReadAll(f)
   481  	if err != nil {
   482  		t.Fatal(err)
   483  	}
   484  
   485  //检查并返回原始数据:
   486  	if !bytes.Equal(dataBytes, gotData) {
   487  		t.Fatalf("Expected: %v, got %v", manifestAddress, gotData)
   488  	}
   489  }
   490  
   491  //TestClientCreateUpdateFeed将检查是否可以通过HTTP客户端创建和更新源。
   492  func TestClientCreateUpdateFeed(t *testing.T) {
   493  
   494  	signer, _ := newTestSigner()
   495  
   496  	srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil)
   497  	client := NewClient(srv.URL)
   498  	defer srv.Close()
   499  
   500  //设置源更新的原始数据
   501  	databytes := []byte("En un lugar de La Mancha, de cuyo nombre no quiero acordarme...")
   502  
   503  //我们的订阅源主题名称
   504  	topic, _ := feed.NewTopic("El Quijote", nil)
   505  	createRequest := feed.NewFirstRequest(topic)
   506  
   507  	createRequest.SetData(databytes)
   508  	if err := createRequest.Sign(signer); err != nil {
   509  		t.Fatalf("Error signing update: %s", err)
   510  	}
   511  
   512  	feedManifestHash, err := client.CreateFeedWithManifest(createRequest)
   513  	if err != nil {
   514  		t.Fatal(err)
   515  	}
   516  
   517  	correctManifestAddrHex := "0e9b645ebc3da167b1d56399adc3276f7a08229301b72a03336be0e7d4b71882"
   518  	if feedManifestHash != correctManifestAddrHex {
   519  		t.Fatalf("Response feed manifest mismatch, expected '%s', got '%s'", correctManifestAddrHex, feedManifestHash)
   520  	}
   521  
   522  	reader, err := client.QueryFeed(nil, correctManifestAddrHex)
   523  	if err != nil {
   524  		t.Fatalf("Error retrieving feed updates: %s", err)
   525  	}
   526  	defer reader.Close()
   527  	gotData, err := ioutil.ReadAll(reader)
   528  	if err != nil {
   529  		t.Fatal(err)
   530  	}
   531  	if !bytes.Equal(databytes, gotData) {
   532  		t.Fatalf("Expected: %v, got %v", databytes, gotData)
   533  	}
   534  
   535  //定义不同的数据
   536  	databytes = []byte("... no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero ...")
   537  
   538  	updateRequest, err := client.GetFeedRequest(nil, correctManifestAddrHex)
   539  	if err != nil {
   540  		t.Fatalf("Error retrieving update request template: %s", err)
   541  	}
   542  
   543  	updateRequest.SetData(databytes)
   544  	if err := updateRequest.Sign(signer); err != nil {
   545  		t.Fatalf("Error signing update: %s", err)
   546  	}
   547  
   548  	if err = client.UpdateFeed(updateRequest); err != nil {
   549  		t.Fatalf("Error updating feed: %s", err)
   550  	}
   551  
   552  	reader, err = client.QueryFeed(nil, correctManifestAddrHex)
   553  	if err != nil {
   554  		t.Fatalf("Error retrieving feed updates: %s", err)
   555  	}
   556  	defer reader.Close()
   557  	gotData, err = ioutil.ReadAll(reader)
   558  	if err != nil {
   559  		t.Fatal(err)
   560  	}
   561  	if !bytes.Equal(databytes, gotData) {
   562  		t.Fatalf("Expected: %v, got %v", databytes, gotData)
   563  	}
   564  
   565  //现在尝试在没有清单的情况下检索源更新
   566  
   567  	fd := &feed.Feed{
   568  		Topic: topic,
   569  		User:  signer.Address(),
   570  	}
   571  
   572  	lookupParams := feed.NewQueryLatest(fd, lookup.NoClue)
   573  	reader, err = client.QueryFeed(lookupParams, "")
   574  	if err != nil {
   575  		t.Fatalf("Error retrieving feed updates: %s", err)
   576  	}
   577  	defer reader.Close()
   578  	gotData, err = ioutil.ReadAll(reader)
   579  	if err != nil {
   580  		t.Fatal(err)
   581  	}
   582  	if !bytes.Equal(databytes, gotData) {
   583  		t.Fatalf("Expected: %v, got %v", databytes, gotData)
   584  	}
   585  }
   586