github.com/zjj1991/quorum@v0.0.0-20190524123704-ae4b0a1e1a19/swarm/api/client/client_test.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser 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 // The go-ethereum library 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 Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package client 18 19 import ( 20 "bytes" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "reflect" 25 "sort" 26 "testing" 27 28 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 29 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/crypto" 32 "github.com/ethereum/go-ethereum/swarm/api" 33 swarmhttp "github.com/ethereum/go-ethereum/swarm/api/http" 34 "github.com/ethereum/go-ethereum/swarm/multihash" 35 "github.com/ethereum/go-ethereum/swarm/storage/feed" 36 ) 37 38 func serverFunc(api *api.API) swarmhttp.TestServer { 39 return swarmhttp.NewServer(api, "") 40 } 41 42 // TestClientUploadDownloadRaw test uploading and downloading raw data to swarm 43 func TestClientUploadDownloadRaw(t *testing.T) { 44 testClientUploadDownloadRaw(false, t) 45 } 46 func TestClientUploadDownloadRawEncrypted(t *testing.T) { 47 testClientUploadDownloadRaw(true, t) 48 } 49 50 func testClientUploadDownloadRaw(toEncrypt bool, t *testing.T) { 51 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 52 defer srv.Close() 53 54 client := NewClient(srv.URL) 55 56 // upload some raw data 57 data := []byte("foo123") 58 hash, err := client.UploadRaw(bytes.NewReader(data), int64(len(data)), toEncrypt) 59 if err != nil { 60 t.Fatal(err) 61 } 62 63 // check we can download the same data 64 res, isEncrypted, err := client.DownloadRaw(hash) 65 if err != nil { 66 t.Fatal(err) 67 } 68 if isEncrypted != toEncrypt { 69 t.Fatalf("Expected encyption status %v got %v", toEncrypt, isEncrypted) 70 } 71 defer res.Close() 72 gotData, err := ioutil.ReadAll(res) 73 if err != nil { 74 t.Fatal(err) 75 } 76 if !bytes.Equal(gotData, data) { 77 t.Fatalf("expected downloaded data to be %q, got %q", data, gotData) 78 } 79 } 80 81 // TestClientUploadDownloadFiles test uploading and downloading files to swarm 82 // manifests 83 func TestClientUploadDownloadFiles(t *testing.T) { 84 testClientUploadDownloadFiles(false, t) 85 } 86 87 func TestClientUploadDownloadFilesEncrypted(t *testing.T) { 88 testClientUploadDownloadFiles(true, t) 89 } 90 91 func testClientUploadDownloadFiles(toEncrypt bool, t *testing.T) { 92 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 93 defer srv.Close() 94 95 client := NewClient(srv.URL) 96 upload := func(manifest, path string, data []byte) string { 97 file := &File{ 98 ReadCloser: ioutil.NopCloser(bytes.NewReader(data)), 99 ManifestEntry: api.ManifestEntry{ 100 Path: path, 101 ContentType: "text/plain", 102 Size: int64(len(data)), 103 }, 104 } 105 hash, err := client.Upload(file, manifest, toEncrypt) 106 if err != nil { 107 t.Fatal(err) 108 } 109 return hash 110 } 111 checkDownload := func(manifest, path string, expected []byte) { 112 file, err := client.Download(manifest, path) 113 if err != nil { 114 t.Fatal(err) 115 } 116 defer file.Close() 117 if file.Size != int64(len(expected)) { 118 t.Fatalf("expected downloaded file to be %d bytes, got %d", len(expected), file.Size) 119 } 120 if file.ContentType != "text/plain" { 121 t.Fatalf("expected downloaded file to have type %q, got %q", "text/plain", file.ContentType) 122 } 123 data, err := ioutil.ReadAll(file) 124 if err != nil { 125 t.Fatal(err) 126 } 127 if !bytes.Equal(data, expected) { 128 t.Fatalf("expected downloaded data to be %q, got %q", expected, data) 129 } 130 } 131 132 // upload a file to the root of a manifest 133 rootData := []byte("some-data") 134 rootHash := upload("", "", rootData) 135 136 // check we can download the root file 137 checkDownload(rootHash, "", rootData) 138 139 // upload another file to the same manifest 140 otherData := []byte("some-other-data") 141 newHash := upload(rootHash, "some/other/path", otherData) 142 143 // check we can download both files from the new manifest 144 checkDownload(newHash, "", rootData) 145 checkDownload(newHash, "some/other/path", otherData) 146 147 // replace the root file with different data 148 newHash = upload(newHash, "", otherData) 149 150 // check both files have the other data 151 checkDownload(newHash, "", otherData) 152 checkDownload(newHash, "some/other/path", otherData) 153 } 154 155 var testDirFiles = []string{ 156 "file1.txt", 157 "file2.txt", 158 "dir1/file3.txt", 159 "dir1/file4.txt", 160 "dir2/file5.txt", 161 "dir2/dir3/file6.txt", 162 "dir2/dir4/file7.txt", 163 "dir2/dir4/file8.txt", 164 } 165 166 func newTestDirectory(t *testing.T) string { 167 dir, err := ioutil.TempDir("", "swarm-client-test") 168 if err != nil { 169 t.Fatal(err) 170 } 171 172 for _, file := range testDirFiles { 173 path := filepath.Join(dir, file) 174 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { 175 os.RemoveAll(dir) 176 t.Fatalf("error creating dir for %s: %s", path, err) 177 } 178 if err := ioutil.WriteFile(path, []byte(file), 0644); err != nil { 179 os.RemoveAll(dir) 180 t.Fatalf("error writing file %s: %s", path, err) 181 } 182 } 183 184 return dir 185 } 186 187 // TestClientUploadDownloadDirectory tests uploading and downloading a 188 // directory of files to a swarm manifest 189 func TestClientUploadDownloadDirectory(t *testing.T) { 190 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 191 defer srv.Close() 192 193 dir := newTestDirectory(t) 194 defer os.RemoveAll(dir) 195 196 // upload the directory 197 client := NewClient(srv.URL) 198 defaultPath := testDirFiles[0] 199 hash, err := client.UploadDirectory(dir, defaultPath, "", false) 200 if err != nil { 201 t.Fatalf("error uploading directory: %s", err) 202 } 203 204 // check we can download the individual files 205 checkDownloadFile := func(path string, expected []byte) { 206 file, err := client.Download(hash, path) 207 if err != nil { 208 t.Fatal(err) 209 } 210 defer file.Close() 211 data, err := ioutil.ReadAll(file) 212 if err != nil { 213 t.Fatal(err) 214 } 215 if !bytes.Equal(data, expected) { 216 t.Fatalf("expected data to be %q, got %q", expected, data) 217 } 218 } 219 for _, file := range testDirFiles { 220 checkDownloadFile(file, []byte(file)) 221 } 222 223 // check we can download the default path 224 checkDownloadFile("", []byte(testDirFiles[0])) 225 226 // check we can download the directory 227 tmp, err := ioutil.TempDir("", "swarm-client-test") 228 if err != nil { 229 t.Fatal(err) 230 } 231 defer os.RemoveAll(tmp) 232 if err := client.DownloadDirectory(hash, "", tmp, ""); err != nil { 233 t.Fatal(err) 234 } 235 for _, file := range testDirFiles { 236 data, err := ioutil.ReadFile(filepath.Join(tmp, file)) 237 if err != nil { 238 t.Fatal(err) 239 } 240 if !bytes.Equal(data, []byte(file)) { 241 t.Fatalf("expected data to be %q, got %q", file, data) 242 } 243 } 244 } 245 246 // TestClientFileList tests listing files in a swarm manifest 247 func TestClientFileList(t *testing.T) { 248 testClientFileList(false, t) 249 } 250 251 func TestClientFileListEncrypted(t *testing.T) { 252 testClientFileList(true, t) 253 } 254 255 func testClientFileList(toEncrypt bool, t *testing.T) { 256 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 257 defer srv.Close() 258 259 dir := newTestDirectory(t) 260 defer os.RemoveAll(dir) 261 262 client := NewClient(srv.URL) 263 hash, err := client.UploadDirectory(dir, "", "", toEncrypt) 264 if err != nil { 265 t.Fatalf("error uploading directory: %s", err) 266 } 267 268 ls := func(prefix string) []string { 269 list, err := client.List(hash, prefix, "") 270 if err != nil { 271 t.Fatal(err) 272 } 273 paths := make([]string, 0, len(list.CommonPrefixes)+len(list.Entries)) 274 paths = append(paths, list.CommonPrefixes...) 275 for _, entry := range list.Entries { 276 paths = append(paths, entry.Path) 277 } 278 sort.Strings(paths) 279 return paths 280 } 281 282 tests := map[string][]string{ 283 "": {"dir1/", "dir2/", "file1.txt", "file2.txt"}, 284 "file": {"file1.txt", "file2.txt"}, 285 "file1": {"file1.txt"}, 286 "file2.txt": {"file2.txt"}, 287 "file12": {}, 288 "dir": {"dir1/", "dir2/"}, 289 "dir1": {"dir1/"}, 290 "dir1/": {"dir1/file3.txt", "dir1/file4.txt"}, 291 "dir1/file": {"dir1/file3.txt", "dir1/file4.txt"}, 292 "dir1/file3.txt": {"dir1/file3.txt"}, 293 "dir1/file34": {}, 294 "dir2/": {"dir2/dir3/", "dir2/dir4/", "dir2/file5.txt"}, 295 "dir2/file": {"dir2/file5.txt"}, 296 "dir2/dir": {"dir2/dir3/", "dir2/dir4/"}, 297 "dir2/dir3/": {"dir2/dir3/file6.txt"}, 298 "dir2/dir4/": {"dir2/dir4/file7.txt", "dir2/dir4/file8.txt"}, 299 "dir2/dir4/file": {"dir2/dir4/file7.txt", "dir2/dir4/file8.txt"}, 300 "dir2/dir4/file7.txt": {"dir2/dir4/file7.txt"}, 301 "dir2/dir4/file78": {}, 302 } 303 for prefix, expected := range tests { 304 actual := ls(prefix) 305 if !reflect.DeepEqual(actual, expected) { 306 t.Fatalf("expected prefix %q to return %v, got %v", prefix, expected, actual) 307 } 308 } 309 } 310 311 // TestClientMultipartUpload tests uploading files to swarm using a multipart 312 // upload 313 func TestClientMultipartUpload(t *testing.T) { 314 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 315 defer srv.Close() 316 317 // define an uploader which uploads testDirFiles with some data 318 data := []byte("some-data") 319 uploader := UploaderFunc(func(upload UploadFn) error { 320 for _, name := range testDirFiles { 321 file := &File{ 322 ReadCloser: ioutil.NopCloser(bytes.NewReader(data)), 323 ManifestEntry: api.ManifestEntry{ 324 Path: name, 325 ContentType: "text/plain", 326 Size: int64(len(data)), 327 }, 328 } 329 if err := upload(file); err != nil { 330 return err 331 } 332 } 333 return nil 334 }) 335 336 // upload the files as a multipart upload 337 client := NewClient(srv.URL) 338 hash, err := client.MultipartUpload("", uploader) 339 if err != nil { 340 t.Fatal(err) 341 } 342 343 // check we can download the individual files 344 checkDownloadFile := func(path string) { 345 file, err := client.Download(hash, path) 346 if err != nil { 347 t.Fatal(err) 348 } 349 defer file.Close() 350 gotData, err := ioutil.ReadAll(file) 351 if err != nil { 352 t.Fatal(err) 353 } 354 if !bytes.Equal(gotData, data) { 355 t.Fatalf("expected data to be %q, got %q", data, gotData) 356 } 357 } 358 for _, file := range testDirFiles { 359 checkDownloadFile(file) 360 } 361 } 362 363 func newTestSigner() (*feed.GenericSigner, error) { 364 privKey, err := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") 365 if err != nil { 366 return nil, err 367 } 368 return feed.NewGenericSigner(privKey), nil 369 } 370 371 // test the transparent resolving of multihash feed updates with bzz:// scheme 372 // 373 // first upload data, and store the multihash to the resulting manifest in a feed update 374 // retrieving the update with the multihash should return the manifest pointing directly to the data 375 // and raw retrieve of that hash should return the data 376 func TestClientCreateFeedMultihash(t *testing.T) { 377 378 signer, _ := newTestSigner() 379 380 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 381 client := NewClient(srv.URL) 382 defer srv.Close() 383 384 // add the data our multihash aliased manifest will point to 385 databytes := []byte("bar") 386 387 swarmHash, err := client.UploadRaw(bytes.NewReader(databytes), int64(len(databytes)), false) 388 if err != nil { 389 t.Fatalf("Error uploading raw test data: %s", err) 390 } 391 392 s := common.FromHex(swarmHash) 393 mh := multihash.ToMultihash(s) 394 395 // our feed topic 396 topic, _ := feed.NewTopic("foo.eth", nil) 397 398 createRequest := feed.NewFirstRequest(topic) 399 400 createRequest.SetData(mh) 401 if err := createRequest.Sign(signer); err != nil { 402 t.Fatalf("Error signing update: %s", err) 403 } 404 405 feedManifestHash, err := client.CreateFeedWithManifest(createRequest) 406 407 if err != nil { 408 t.Fatalf("Error creating feed manifest: %s", err) 409 } 410 411 correctManifestAddrHex := "bb056a5264c295c2b0f613c8409b9c87ce9d71576ace02458160df4cc894210b" 412 if feedManifestHash != correctManifestAddrHex { 413 t.Fatalf("Response feed manifest mismatch, expected '%s', got '%s'", correctManifestAddrHex, feedManifestHash) 414 } 415 416 // Check we get a not found error when trying to get feed updates with a made-up manifest 417 _, err = client.QueryFeed(nil, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") 418 if err != ErrNoFeedUpdatesFound { 419 t.Fatalf("Expected to receive ErrNoFeedUpdatesFound error. Got: %s", err) 420 } 421 422 reader, err := client.QueryFeed(nil, correctManifestAddrHex) 423 if err != nil { 424 t.Fatalf("Error retrieving feed updates: %s", err) 425 } 426 defer reader.Close() 427 gotData, err := ioutil.ReadAll(reader) 428 if err != nil { 429 t.Fatal(err) 430 } 431 if !bytes.Equal(mh, gotData) { 432 t.Fatalf("Expected: %v, got %v", mh, gotData) 433 } 434 435 } 436 437 // TestClientCreateUpdateFeed will check that feeds can be created and updated via the HTTP client. 438 func TestClientCreateUpdateFeed(t *testing.T) { 439 440 signer, _ := newTestSigner() 441 442 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 443 client := NewClient(srv.URL) 444 defer srv.Close() 445 446 // set raw data for the feed update 447 databytes := []byte("En un lugar de La Mancha, de cuyo nombre no quiero acordarme...") 448 449 // our feed topic name 450 topic, _ := feed.NewTopic("El Quijote", nil) 451 createRequest := feed.NewFirstRequest(topic) 452 453 createRequest.SetData(databytes) 454 if err := createRequest.Sign(signer); err != nil { 455 t.Fatalf("Error signing update: %s", err) 456 } 457 458 feedManifestHash, err := client.CreateFeedWithManifest(createRequest) 459 if err != nil { 460 t.Fatal(err) 461 } 462 463 correctManifestAddrHex := "0e9b645ebc3da167b1d56399adc3276f7a08229301b72a03336be0e7d4b71882" 464 if feedManifestHash != correctManifestAddrHex { 465 t.Fatalf("Response feed manifest mismatch, expected '%s', got '%s'", correctManifestAddrHex, feedManifestHash) 466 } 467 468 reader, err := client.QueryFeed(nil, correctManifestAddrHex) 469 if err != nil { 470 t.Fatalf("Error retrieving feed updates: %s", err) 471 } 472 defer reader.Close() 473 gotData, err := ioutil.ReadAll(reader) 474 if err != nil { 475 t.Fatal(err) 476 } 477 if !bytes.Equal(databytes, gotData) { 478 t.Fatalf("Expected: %v, got %v", databytes, gotData) 479 } 480 481 // define different data 482 databytes = []byte("... no ha mucho tiempo que vivĂa un hidalgo de los de lanza en astillero ...") 483 484 updateRequest, err := client.GetFeedRequest(nil, correctManifestAddrHex) 485 if err != nil { 486 t.Fatalf("Error retrieving update request template: %s", err) 487 } 488 489 updateRequest.SetData(databytes) 490 if err := updateRequest.Sign(signer); err != nil { 491 t.Fatalf("Error signing update: %s", err) 492 } 493 494 if err = client.UpdateFeed(updateRequest); err != nil { 495 t.Fatalf("Error updating feed: %s", err) 496 } 497 498 reader, err = client.QueryFeed(nil, correctManifestAddrHex) 499 if err != nil { 500 t.Fatalf("Error retrieving feed updates: %s", err) 501 } 502 defer reader.Close() 503 gotData, err = ioutil.ReadAll(reader) 504 if err != nil { 505 t.Fatal(err) 506 } 507 if !bytes.Equal(databytes, gotData) { 508 t.Fatalf("Expected: %v, got %v", databytes, gotData) 509 } 510 511 // now try retrieving feed updates without a manifest 512 513 fd := &feed.Feed{ 514 Topic: topic, 515 User: signer.Address(), 516 } 517 518 lookupParams := feed.NewQueryLatest(fd, lookup.NoClue) 519 reader, err = client.QueryFeed(lookupParams, "") 520 if err != nil { 521 t.Fatalf("Error retrieving feed updates: %s", err) 522 } 523 defer reader.Close() 524 gotData, err = ioutil.ReadAll(reader) 525 if err != nil { 526 t.Fatal(err) 527 } 528 if !bytes.Equal(databytes, gotData) { 529 t.Fatalf("Expected: %v, got %v", databytes, gotData) 530 } 531 }