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