github.com/alexdevranger/node-1.8.27@v0.0.0-20221128213301-aa5841e41d2d/cmd/swarm/manifest_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of go-dubxcoin. 3 // 4 // go-dubxcoin 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 "io/ioutil" 22 "os" 23 "path/filepath" 24 "runtime" 25 "testing" 26 27 "github.com/alexdevranger/node-1.8.27/swarm/api" 28 swarm "github.com/alexdevranger/node-1.8.27/swarm/api/client" 29 swarmhttp "github.com/alexdevranger/node-1.8.27/swarm/api/http" 30 ) 31 32 // TestManifestChange tests manifest add, update and remove 33 // cli commands without encryption. 34 func TestManifestChange(t *testing.T) { 35 if runtime.GOOS == "windows" { 36 t.Skip() 37 } 38 39 testManifestChange(t, false) 40 } 41 42 // TestManifestChange tests manifest add, update and remove 43 // cli commands with encryption enabled. 44 func TestManifestChangeEncrypted(t *testing.T) { 45 if runtime.GOOS == "windows" { 46 t.Skip() 47 } 48 49 testManifestChange(t, true) 50 } 51 52 // testManifestChange performs cli commands: 53 // - manifest add 54 // - manifest update 55 // - manifest remove 56 // on a manifest, testing the functionality of this 57 // comands on paths that are in root manifest or a nested one. 58 // Argument encrypt controls whether to use encryption or not. 59 func testManifestChange(t *testing.T, encrypt bool) { 60 t.Parallel() 61 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 62 defer srv.Close() 63 64 tmp, err := ioutil.TempDir("", "swarm-manifest-test") 65 if err != nil { 66 t.Fatal(err) 67 } 68 defer os.RemoveAll(tmp) 69 70 origDir := filepath.Join(tmp, "orig") 71 if err := os.Mkdir(origDir, 0777); err != nil { 72 t.Fatal(err) 73 } 74 75 indexDataFilename := filepath.Join(origDir, "index.html") 76 err = ioutil.WriteFile(indexDataFilename, []byte("<h1>Test</h1>"), 0666) 77 if err != nil { 78 t.Fatal(err) 79 } 80 // Files paths robots.txt and robots.html share the same prefix "robots." 81 // which will result a manifest with a nested manifest under path "robots.". 82 // This will allow testing manifest changes on both root and nested manifest. 83 err = ioutil.WriteFile(filepath.Join(origDir, "robots.txt"), []byte("Disallow: /"), 0666) 84 if err != nil { 85 t.Fatal(err) 86 } 87 err = ioutil.WriteFile(filepath.Join(origDir, "robots.html"), []byte("<strong>No Robots Allowed</strong>"), 0666) 88 if err != nil { 89 t.Fatal(err) 90 } 91 err = ioutil.WriteFile(filepath.Join(origDir, "mutants.txt"), []byte("Frank\nMarcus"), 0666) 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 args := []string{ 97 "--bzzapi", 98 srv.URL, 99 "--recursive", 100 "--defaultpath", 101 indexDataFilename, 102 "up", 103 origDir, 104 } 105 if encrypt { 106 args = append(args, "--encrypt") 107 } 108 109 origManifestHash := runSwarmExpectHash(t, args...) 110 111 checkHashLength(t, origManifestHash, encrypt) 112 113 client := swarm.NewClient(srv.URL) 114 115 // upload a new file and use its manifest to add it the original manifest. 116 t.Run("add", func(t *testing.T) { 117 humansData := []byte("Ann\nBob") 118 humansDataFilename := filepath.Join(tmp, "humans.txt") 119 err = ioutil.WriteFile(humansDataFilename, humansData, 0666) 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 humansManifestHash := runSwarmExpectHash(t, 125 "--bzzapi", 126 srv.URL, 127 "up", 128 humansDataFilename, 129 ) 130 131 newManifestHash := runSwarmExpectHash(t, 132 "--bzzapi", 133 srv.URL, 134 "manifest", 135 "add", 136 origManifestHash, 137 "humans.txt", 138 humansManifestHash, 139 ) 140 141 checkHashLength(t, newManifestHash, encrypt) 142 143 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 144 145 var found bool 146 for _, e := range newManifest.Entries { 147 if e.Path == "humans.txt" { 148 found = true 149 if e.Size != int64(len(humansData)) { 150 t.Errorf("expected humans.txt size %v, got %v", len(humansData), e.Size) 151 } 152 if e.ModTime.IsZero() { 153 t.Errorf("got zero mod time for humans.txt") 154 } 155 ct := "text/plain; charset=utf-8" 156 if e.ContentType != ct { 157 t.Errorf("expected content type %q, got %q", ct, e.ContentType) 158 } 159 break 160 } 161 } 162 if !found { 163 t.Fatal("no humans.txt in new manifest") 164 } 165 166 checkFile(t, client, newManifestHash, "humans.txt", humansData) 167 }) 168 169 // upload a new file and use its manifest to add it the original manifest, 170 // but ensure that the file will be in the nested manifest of the original one. 171 t.Run("add nested", func(t *testing.T) { 172 robotsData := []byte(`{"disallow": "/"}`) 173 robotsDataFilename := filepath.Join(tmp, "robots.json") 174 err = ioutil.WriteFile(robotsDataFilename, robotsData, 0666) 175 if err != nil { 176 t.Fatal(err) 177 } 178 179 robotsManifestHash := runSwarmExpectHash(t, 180 "--bzzapi", 181 srv.URL, 182 "up", 183 robotsDataFilename, 184 ) 185 186 newManifestHash := runSwarmExpectHash(t, 187 "--bzzapi", 188 srv.URL, 189 "manifest", 190 "add", 191 origManifestHash, 192 "robots.json", 193 robotsManifestHash, 194 ) 195 196 checkHashLength(t, newManifestHash, encrypt) 197 198 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 199 200 var found bool 201 loop: 202 for _, e := range newManifest.Entries { 203 if e.Path == "robots." { 204 nestedManifest := downloadManifest(t, client, e.Hash, encrypt) 205 for _, e := range nestedManifest.Entries { 206 if e.Path == "json" { 207 found = true 208 if e.Size != int64(len(robotsData)) { 209 t.Errorf("expected robots.json size %v, got %v", len(robotsData), e.Size) 210 } 211 if e.ModTime.IsZero() { 212 t.Errorf("got zero mod time for robots.json") 213 } 214 ct := "application/json" 215 if e.ContentType != ct { 216 t.Errorf("expected content type %q, got %q", ct, e.ContentType) 217 } 218 break loop 219 } 220 } 221 } 222 } 223 if !found { 224 t.Fatal("no robots.json in new manifest") 225 } 226 227 checkFile(t, client, newManifestHash, "robots.json", robotsData) 228 }) 229 230 // upload a new file and use its manifest to change the file it the original manifest. 231 t.Run("update", func(t *testing.T) { 232 indexData := []byte("<h1>Ethereum Swarm</h1>") 233 indexDataFilename := filepath.Join(tmp, "index.html") 234 err = ioutil.WriteFile(indexDataFilename, indexData, 0666) 235 if err != nil { 236 t.Fatal(err) 237 } 238 239 indexManifestHash := runSwarmExpectHash(t, 240 "--bzzapi", 241 srv.URL, 242 "up", 243 indexDataFilename, 244 ) 245 246 newManifestHash := runSwarmExpectHash(t, 247 "--bzzapi", 248 srv.URL, 249 "manifest", 250 "update", 251 origManifestHash, 252 "index.html", 253 indexManifestHash, 254 ) 255 256 checkHashLength(t, newManifestHash, encrypt) 257 258 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 259 260 var found bool 261 for _, e := range newManifest.Entries { 262 if e.Path == "index.html" { 263 found = true 264 if e.Size != int64(len(indexData)) { 265 t.Errorf("expected index.html size %v, got %v", len(indexData), e.Size) 266 } 267 if e.ModTime.IsZero() { 268 t.Errorf("got zero mod time for index.html") 269 } 270 ct := "text/html; charset=utf-8" 271 if e.ContentType != ct { 272 t.Errorf("expected content type %q, got %q", ct, e.ContentType) 273 } 274 break 275 } 276 } 277 if !found { 278 t.Fatal("no index.html in new manifest") 279 } 280 281 checkFile(t, client, newManifestHash, "index.html", indexData) 282 283 // check default entry change 284 checkFile(t, client, newManifestHash, "", indexData) 285 }) 286 287 // upload a new file and use its manifest to change the file it the original manifest, 288 // but ensure that the file is in the nested manifest of the original one. 289 t.Run("update nested", func(t *testing.T) { 290 robotsData := []byte(`<string>Only humans allowed!!!</strong>`) 291 robotsDataFilename := filepath.Join(tmp, "robots.html") 292 err = ioutil.WriteFile(robotsDataFilename, robotsData, 0666) 293 if err != nil { 294 t.Fatal(err) 295 } 296 297 humansManifestHash := runSwarmExpectHash(t, 298 "--bzzapi", 299 srv.URL, 300 "up", 301 robotsDataFilename, 302 ) 303 304 newManifestHash := runSwarmExpectHash(t, 305 "--bzzapi", 306 srv.URL, 307 "manifest", 308 "update", 309 origManifestHash, 310 "robots.html", 311 humansManifestHash, 312 ) 313 314 checkHashLength(t, newManifestHash, encrypt) 315 316 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 317 318 var found bool 319 loop: 320 for _, e := range newManifest.Entries { 321 if e.Path == "robots." { 322 nestedManifest := downloadManifest(t, client, e.Hash, encrypt) 323 for _, e := range nestedManifest.Entries { 324 if e.Path == "html" { 325 found = true 326 if e.Size != int64(len(robotsData)) { 327 t.Errorf("expected robots.html size %v, got %v", len(robotsData), e.Size) 328 } 329 if e.ModTime.IsZero() { 330 t.Errorf("got zero mod time for robots.html") 331 } 332 ct := "text/html; charset=utf-8" 333 if e.ContentType != ct { 334 t.Errorf("expected content type %q, got %q", ct, e.ContentType) 335 } 336 break loop 337 } 338 } 339 } 340 } 341 if !found { 342 t.Fatal("no robots.html in new manifest") 343 } 344 345 checkFile(t, client, newManifestHash, "robots.html", robotsData) 346 }) 347 348 // remove a file from the manifest. 349 t.Run("remove", func(t *testing.T) { 350 newManifestHash := runSwarmExpectHash(t, 351 "--bzzapi", 352 srv.URL, 353 "manifest", 354 "remove", 355 origManifestHash, 356 "mutants.txt", 357 ) 358 359 checkHashLength(t, newManifestHash, encrypt) 360 361 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 362 363 var found bool 364 for _, e := range newManifest.Entries { 365 if e.Path == "mutants.txt" { 366 found = true 367 break 368 } 369 } 370 if found { 371 t.Fatal("mutants.txt is not removed") 372 } 373 }) 374 375 // remove a file from the manifest, but ensure that the file is in 376 // the nested manifest of the original one. 377 t.Run("remove nested", func(t *testing.T) { 378 newManifestHash := runSwarmExpectHash(t, 379 "--bzzapi", 380 srv.URL, 381 "manifest", 382 "remove", 383 origManifestHash, 384 "robots.html", 385 ) 386 387 checkHashLength(t, newManifestHash, encrypt) 388 389 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 390 391 var found bool 392 loop: 393 for _, e := range newManifest.Entries { 394 if e.Path == "robots." { 395 nestedManifest := downloadManifest(t, client, e.Hash, encrypt) 396 for _, e := range nestedManifest.Entries { 397 if e.Path == "html" { 398 found = true 399 break loop 400 } 401 } 402 } 403 } 404 if found { 405 t.Fatal("robots.html in not removed") 406 } 407 }) 408 } 409 410 // TestNestedDefaultEntryUpdate tests if the default entry is updated 411 // if the file in nested manifest used for it is also updated. 412 func TestNestedDefaultEntryUpdate(t *testing.T) { 413 if runtime.GOOS == "windows" { 414 t.Skip() 415 } 416 417 testNestedDefaultEntryUpdate(t, false) 418 } 419 420 // TestNestedDefaultEntryUpdateEncrypted tests if the default entry 421 // of encrypted upload is updated if the file in nested manifest 422 // used for it is also updated. 423 func TestNestedDefaultEntryUpdateEncrypted(t *testing.T) { 424 if runtime.GOOS == "windows" { 425 t.Skip() 426 } 427 428 testNestedDefaultEntryUpdate(t, true) 429 } 430 431 func testNestedDefaultEntryUpdate(t *testing.T, encrypt bool) { 432 t.Parallel() 433 srv := swarmhttp.NewTestSwarmServer(t, serverFunc, nil) 434 defer srv.Close() 435 436 tmp, err := ioutil.TempDir("", "swarm-manifest-test") 437 if err != nil { 438 t.Fatal(err) 439 } 440 defer os.RemoveAll(tmp) 441 442 origDir := filepath.Join(tmp, "orig") 443 if err := os.Mkdir(origDir, 0777); err != nil { 444 t.Fatal(err) 445 } 446 447 indexData := []byte("<h1>Test</h1>") 448 indexDataFilename := filepath.Join(origDir, "index.html") 449 err = ioutil.WriteFile(indexDataFilename, indexData, 0666) 450 if err != nil { 451 t.Fatal(err) 452 } 453 // Add another file with common prefix as the default entry to test updates of 454 // default entry with nested manifests. 455 err = ioutil.WriteFile(filepath.Join(origDir, "index.txt"), []byte("Test"), 0666) 456 if err != nil { 457 t.Fatal(err) 458 } 459 460 args := []string{ 461 "--bzzapi", 462 srv.URL, 463 "--recursive", 464 "--defaultpath", 465 indexDataFilename, 466 "up", 467 origDir, 468 } 469 if encrypt { 470 args = append(args, "--encrypt") 471 } 472 473 origManifestHash := runSwarmExpectHash(t, args...) 474 475 checkHashLength(t, origManifestHash, encrypt) 476 477 client := swarm.NewClient(srv.URL) 478 479 newIndexData := []byte("<h1>Ethereum Swarm</h1>") 480 newIndexDataFilename := filepath.Join(tmp, "index.html") 481 err = ioutil.WriteFile(newIndexDataFilename, newIndexData, 0666) 482 if err != nil { 483 t.Fatal(err) 484 } 485 486 newIndexManifestHash := runSwarmExpectHash(t, 487 "--bzzapi", 488 srv.URL, 489 "up", 490 newIndexDataFilename, 491 ) 492 493 newManifestHash := runSwarmExpectHash(t, 494 "--bzzapi", 495 srv.URL, 496 "manifest", 497 "update", 498 origManifestHash, 499 "index.html", 500 newIndexManifestHash, 501 ) 502 503 checkHashLength(t, newManifestHash, encrypt) 504 505 newManifest := downloadManifest(t, client, newManifestHash, encrypt) 506 507 var found bool 508 for _, e := range newManifest.Entries { 509 if e.Path == "index." { 510 found = true 511 newManifest = downloadManifest(t, client, e.Hash, encrypt) 512 break 513 } 514 } 515 if !found { 516 t.Fatal("no index. path in new manifest") 517 } 518 519 found = false 520 for _, e := range newManifest.Entries { 521 if e.Path == "html" { 522 found = true 523 if e.Size != int64(len(newIndexData)) { 524 t.Errorf("expected index.html size %v, got %v", len(newIndexData), e.Size) 525 } 526 if e.ModTime.IsZero() { 527 t.Errorf("got zero mod time for index.html") 528 } 529 ct := "text/html; charset=utf-8" 530 if e.ContentType != ct { 531 t.Errorf("expected content type %q, got %q", ct, e.ContentType) 532 } 533 break 534 } 535 } 536 if !found { 537 t.Fatal("no html in new manifest") 538 } 539 540 checkFile(t, client, newManifestHash, "index.html", newIndexData) 541 542 // check default entry change 543 checkFile(t, client, newManifestHash, "", newIndexData) 544 } 545 546 func runSwarmExpectHash(t *testing.T, args ...string) (hash string) { 547 t.Helper() 548 hashRegexp := `[a-f\d]{64,128}` 549 up := runSwarm(t, args...) 550 _, matches := up.ExpectRegexp(hashRegexp) 551 up.ExpectExit() 552 553 if len(matches) < 1 { 554 t.Fatal("no matches found") 555 } 556 return matches[0] 557 } 558 559 func checkHashLength(t *testing.T, hash string, encrypted bool) { 560 t.Helper() 561 l := len(hash) 562 if encrypted && l != 128 { 563 t.Errorf("expected hash length 128, got %v", l) 564 } 565 if !encrypted && l != 64 { 566 t.Errorf("expected hash length 64, got %v", l) 567 } 568 } 569 570 func downloadManifest(t *testing.T, client *swarm.Client, hash string, encrypted bool) (manifest *api.Manifest) { 571 t.Helper() 572 m, isEncrypted, err := client.DownloadManifest(hash) 573 if err != nil { 574 t.Fatal(err) 575 } 576 577 if encrypted != isEncrypted { 578 t.Error("new manifest encryption flag is not correct") 579 } 580 return m 581 } 582 583 func checkFile(t *testing.T, client *swarm.Client, hash, path string, expected []byte) { 584 t.Helper() 585 f, err := client.Download(hash, path) 586 if err != nil { 587 t.Fatal(err) 588 } 589 590 got, err := ioutil.ReadAll(f) 591 if err != nil { 592 t.Fatal(err) 593 } 594 if !bytes.Equal(got, expected) { 595 t.Errorf("expected file content %q, got %q", expected, got) 596 } 597 }