github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/importer/trickle/trickle_test.go (about) 1 package trickle 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 mrand "math/rand" 9 "os" 10 "testing" 11 12 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 13 chunk "github.com/ipfs/go-ipfs/importer/chunk" 14 h "github.com/ipfs/go-ipfs/importer/helpers" 15 merkledag "github.com/ipfs/go-ipfs/merkledag" 16 mdtest "github.com/ipfs/go-ipfs/merkledag/test" 17 pin "github.com/ipfs/go-ipfs/pin" 18 ft "github.com/ipfs/go-ipfs/unixfs" 19 uio "github.com/ipfs/go-ipfs/unixfs/io" 20 u "github.com/ipfs/go-ipfs/util" 21 ) 22 23 func buildTestDag(ds merkledag.DAGService, spl chunk.Splitter) (*merkledag.Node, error) { 24 // Start the splitter 25 blkch, errs := chunk.Chan(spl) 26 27 dbp := h.DagBuilderParams{ 28 Dagserv: ds, 29 Maxlinks: h.DefaultLinksPerBlock, 30 } 31 32 nd, err := TrickleLayout(dbp.New(blkch, errs)) 33 if err != nil { 34 return nil, err 35 } 36 37 return nd, VerifyTrickleDagStructure(nd, ds, dbp.Maxlinks, layerRepeat) 38 } 39 40 //Test where calls to read are smaller than the chunk size 41 func TestSizeBasedSplit(t *testing.T) { 42 if testing.Short() { 43 t.SkipNow() 44 } 45 bs := chunk.SizeSplitterGen(512) 46 testFileConsistency(t, bs, 32*512) 47 48 bs = chunk.SizeSplitterGen(4096) 49 testFileConsistency(t, bs, 32*4096) 50 51 // Uneven offset 52 testFileConsistency(t, bs, 31*4095) 53 } 54 55 func dup(b []byte) []byte { 56 o := make([]byte, len(b)) 57 copy(o, b) 58 return o 59 } 60 61 func testFileConsistency(t *testing.T, bs chunk.SplitterGen, nbytes int) { 62 should := make([]byte, nbytes) 63 u.NewTimeSeededRand().Read(should) 64 65 read := bytes.NewReader(should) 66 ds := mdtest.Mock() 67 nd, err := buildTestDag(ds, bs(read)) 68 if err != nil { 69 t.Fatal(err) 70 } 71 72 r, err := uio.NewDagReader(context.Background(), nd, ds) 73 if err != nil { 74 t.Fatal(err) 75 } 76 77 out, err := ioutil.ReadAll(r) 78 if err != nil { 79 t.Fatal(err) 80 } 81 82 err = arrComp(out, should) 83 if err != nil { 84 t.Fatal(err) 85 } 86 } 87 88 func TestBuilderConsistency(t *testing.T) { 89 nbytes := 100000 90 buf := new(bytes.Buffer) 91 io.CopyN(buf, u.NewTimeSeededRand(), int64(nbytes)) 92 should := dup(buf.Bytes()) 93 dagserv := mdtest.Mock() 94 nd, err := buildTestDag(dagserv, chunk.DefaultSplitter(buf)) 95 if err != nil { 96 t.Fatal(err) 97 } 98 r, err := uio.NewDagReader(context.Background(), nd, dagserv) 99 if err != nil { 100 t.Fatal(err) 101 } 102 103 out, err := ioutil.ReadAll(r) 104 if err != nil { 105 t.Fatal(err) 106 } 107 108 err = arrComp(out, should) 109 if err != nil { 110 t.Fatal(err) 111 } 112 } 113 114 func arrComp(a, b []byte) error { 115 if len(a) != len(b) { 116 return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b)) 117 } 118 for i, v := range a { 119 if v != b[i] { 120 return fmt.Errorf("Arrays differ at index: %d", i) 121 } 122 } 123 return nil 124 } 125 126 type dagservAndPinner struct { 127 ds merkledag.DAGService 128 mp pin.ManualPinner 129 } 130 131 func TestIndirectBlocks(t *testing.T) { 132 splitter := chunk.SizeSplitterGen(512) 133 nbytes := 1024 * 1024 134 buf := make([]byte, nbytes) 135 u.NewTimeSeededRand().Read(buf) 136 137 read := bytes.NewReader(buf) 138 139 ds := mdtest.Mock() 140 dag, err := buildTestDag(ds, splitter(read)) 141 if err != nil { 142 t.Fatal(err) 143 } 144 145 reader, err := uio.NewDagReader(context.Background(), dag, ds) 146 if err != nil { 147 t.Fatal(err) 148 } 149 150 out, err := ioutil.ReadAll(reader) 151 if err != nil { 152 t.Fatal(err) 153 } 154 155 if !bytes.Equal(out, buf) { 156 t.Fatal("Not equal!") 157 } 158 } 159 160 func TestSeekingBasic(t *testing.T) { 161 nbytes := int64(10 * 1024) 162 should := make([]byte, nbytes) 163 u.NewTimeSeededRand().Read(should) 164 165 read := bytes.NewReader(should) 166 ds := mdtest.Mock() 167 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 512)) 168 if err != nil { 169 t.Fatal(err) 170 } 171 172 rs, err := uio.NewDagReader(context.Background(), nd, ds) 173 if err != nil { 174 t.Fatal(err) 175 } 176 177 start := int64(4000) 178 n, err := rs.Seek(start, os.SEEK_SET) 179 if err != nil { 180 t.Fatal(err) 181 } 182 if n != start { 183 t.Fatal("Failed to seek to correct offset") 184 } 185 186 out, err := ioutil.ReadAll(rs) 187 if err != nil { 188 t.Fatal(err) 189 } 190 191 err = arrComp(out, should[start:]) 192 if err != nil { 193 t.Fatal(err) 194 } 195 } 196 197 func TestSeekToBegin(t *testing.T) { 198 nbytes := int64(10 * 1024) 199 should := make([]byte, nbytes) 200 u.NewTimeSeededRand().Read(should) 201 202 read := bytes.NewReader(should) 203 ds := mdtest.Mock() 204 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 rs, err := uio.NewDagReader(context.Background(), nd, ds) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 n, err := io.CopyN(ioutil.Discard, rs, 1024*4) 215 if err != nil { 216 t.Fatal(err) 217 } 218 if n != 4096 { 219 t.Fatal("Copy didnt copy enough bytes") 220 } 221 222 seeked, err := rs.Seek(0, os.SEEK_SET) 223 if err != nil { 224 t.Fatal(err) 225 } 226 if seeked != 0 { 227 t.Fatal("Failed to seek to beginning") 228 } 229 230 out, err := ioutil.ReadAll(rs) 231 if err != nil { 232 t.Fatal(err) 233 } 234 235 err = arrComp(out, should) 236 if err != nil { 237 t.Fatal(err) 238 } 239 } 240 241 func TestSeekToAlmostBegin(t *testing.T) { 242 nbytes := int64(10 * 1024) 243 should := make([]byte, nbytes) 244 u.NewTimeSeededRand().Read(should) 245 246 read := bytes.NewReader(should) 247 ds := mdtest.Mock() 248 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) 249 if err != nil { 250 t.Fatal(err) 251 } 252 253 rs, err := uio.NewDagReader(context.Background(), nd, ds) 254 if err != nil { 255 t.Fatal(err) 256 } 257 258 n, err := io.CopyN(ioutil.Discard, rs, 1024*4) 259 if err != nil { 260 t.Fatal(err) 261 } 262 if n != 4096 { 263 t.Fatal("Copy didnt copy enough bytes") 264 } 265 266 seeked, err := rs.Seek(1, os.SEEK_SET) 267 if err != nil { 268 t.Fatal(err) 269 } 270 if seeked != 1 { 271 t.Fatal("Failed to seek to almost beginning") 272 } 273 274 out, err := ioutil.ReadAll(rs) 275 if err != nil { 276 t.Fatal(err) 277 } 278 279 err = arrComp(out, should[1:]) 280 if err != nil { 281 t.Fatal(err) 282 } 283 } 284 285 func TestSeekEnd(t *testing.T) { 286 nbytes := int64(50 * 1024) 287 should := make([]byte, nbytes) 288 u.NewTimeSeededRand().Read(should) 289 290 read := bytes.NewReader(should) 291 ds := mdtest.Mock() 292 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) 293 if err != nil { 294 t.Fatal(err) 295 } 296 297 rs, err := uio.NewDagReader(context.Background(), nd, ds) 298 if err != nil { 299 t.Fatal(err) 300 } 301 302 seeked, err := rs.Seek(0, os.SEEK_END) 303 if err != nil { 304 t.Fatal(err) 305 } 306 if seeked != nbytes { 307 t.Fatal("Failed to seek to end") 308 } 309 } 310 311 func TestSeekEndSingleBlockFile(t *testing.T) { 312 nbytes := int64(100) 313 should := make([]byte, nbytes) 314 u.NewTimeSeededRand().Read(should) 315 316 read := bytes.NewReader(should) 317 ds := mdtest.Mock() 318 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 5000)) 319 if err != nil { 320 t.Fatal(err) 321 } 322 323 rs, err := uio.NewDagReader(context.Background(), nd, ds) 324 if err != nil { 325 t.Fatal(err) 326 } 327 328 seeked, err := rs.Seek(0, os.SEEK_END) 329 if err != nil { 330 t.Fatal(err) 331 } 332 if seeked != nbytes { 333 t.Fatal("Failed to seek to end") 334 } 335 } 336 337 func TestSeekingStress(t *testing.T) { 338 nbytes := int64(1024 * 1024) 339 should := make([]byte, nbytes) 340 u.NewTimeSeededRand().Read(should) 341 342 read := bytes.NewReader(should) 343 ds := mdtest.Mock() 344 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 1000)) 345 if err != nil { 346 t.Fatal(err) 347 } 348 349 rs, err := uio.NewDagReader(context.Background(), nd, ds) 350 if err != nil { 351 t.Fatal(err) 352 } 353 354 testbuf := make([]byte, nbytes) 355 for i := 0; i < 50; i++ { 356 offset := mrand.Intn(int(nbytes)) 357 l := int(nbytes) - offset 358 n, err := rs.Seek(int64(offset), os.SEEK_SET) 359 if err != nil { 360 t.Fatal(err) 361 } 362 if n != int64(offset) { 363 t.Fatal("Seek failed to move to correct position") 364 } 365 366 nread, err := rs.Read(testbuf[:l]) 367 if err != nil { 368 t.Fatal(err) 369 } 370 if nread != l { 371 t.Fatal("Failed to read enough bytes") 372 } 373 374 err = arrComp(testbuf[:l], should[offset:offset+l]) 375 if err != nil { 376 t.Fatal(err) 377 } 378 } 379 380 } 381 382 func TestSeekingConsistency(t *testing.T) { 383 nbytes := int64(128 * 1024) 384 should := make([]byte, nbytes) 385 u.NewTimeSeededRand().Read(should) 386 387 read := bytes.NewReader(should) 388 ds := mdtest.Mock() 389 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) 390 if err != nil { 391 t.Fatal(err) 392 } 393 394 rs, err := uio.NewDagReader(context.Background(), nd, ds) 395 if err != nil { 396 t.Fatal(err) 397 } 398 399 out := make([]byte, nbytes) 400 401 for coff := nbytes - 4096; coff >= 0; coff -= 4096 { 402 t.Log(coff) 403 n, err := rs.Seek(coff, os.SEEK_SET) 404 if err != nil { 405 t.Fatal(err) 406 } 407 if n != coff { 408 t.Fatal("wasnt able to seek to the right position") 409 } 410 nread, err := rs.Read(out[coff : coff+4096]) 411 if err != nil { 412 t.Fatal(err) 413 } 414 if nread != 4096 { 415 t.Fatal("didnt read the correct number of bytes") 416 } 417 } 418 419 err = arrComp(out, should) 420 if err != nil { 421 t.Fatal(err) 422 } 423 } 424 425 func TestAppend(t *testing.T) { 426 nbytes := int64(128 * 1024) 427 should := make([]byte, nbytes) 428 u.NewTimeSeededRand().Read(should) 429 430 // Reader for half the bytes 431 read := bytes.NewReader(should[:nbytes/2]) 432 ds := mdtest.Mock() 433 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) 434 if err != nil { 435 t.Fatal(err) 436 } 437 438 dbp := &h.DagBuilderParams{ 439 Dagserv: ds, 440 Maxlinks: h.DefaultLinksPerBlock, 441 } 442 443 r := bytes.NewReader(should[nbytes/2:]) 444 blks, errs := chunk.Chan(chunk.NewSizeSplitter(r, 500)) 445 446 ctx := context.Background() 447 nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) 448 if err != nil { 449 t.Fatal(err) 450 } 451 452 err = VerifyTrickleDagStructure(nnode, ds, dbp.Maxlinks, layerRepeat) 453 if err != nil { 454 t.Fatal(err) 455 } 456 457 fread, err := uio.NewDagReader(ctx, nnode, ds) 458 if err != nil { 459 t.Fatal(err) 460 } 461 462 out, err := ioutil.ReadAll(fread) 463 if err != nil { 464 t.Fatal(err) 465 } 466 467 err = arrComp(out, should) 468 if err != nil { 469 t.Fatal(err) 470 } 471 } 472 473 // This test appends one byte at a time to an empty file 474 func TestMultipleAppends(t *testing.T) { 475 ds := mdtest.Mock() 476 477 // TODO: fix small size appends and make this number bigger 478 nbytes := int64(1000) 479 should := make([]byte, nbytes) 480 u.NewTimeSeededRand().Read(should) 481 482 read := bytes.NewReader(nil) 483 nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) 484 if err != nil { 485 t.Fatal(err) 486 } 487 488 dbp := &h.DagBuilderParams{ 489 Dagserv: ds, 490 Maxlinks: 4, 491 } 492 493 spl := chunk.SizeSplitterGen(500) 494 495 ctx := context.Background() 496 for i := 0; i < len(should); i++ { 497 blks, errs := chunk.Chan(spl(bytes.NewReader(should[i : i+1]))) 498 499 nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) 500 if err != nil { 501 t.Fatal(err) 502 } 503 504 err = VerifyTrickleDagStructure(nnode, ds, dbp.Maxlinks, layerRepeat) 505 if err != nil { 506 t.Fatal(err) 507 } 508 509 fread, err := uio.NewDagReader(ctx, nnode, ds) 510 if err != nil { 511 t.Fatal(err) 512 } 513 514 out, err := ioutil.ReadAll(fread) 515 if err != nil { 516 t.Fatal(err) 517 } 518 519 err = arrComp(out, should[:i+1]) 520 if err != nil { 521 t.Fatal(err) 522 } 523 } 524 } 525 526 func TestAppendSingleBytesToEmpty(t *testing.T) { 527 ds := mdtest.Mock() 528 529 data := []byte("AB") 530 531 nd := new(merkledag.Node) 532 nd.Data = ft.FilePBData(nil, 0) 533 534 dbp := &h.DagBuilderParams{ 535 Dagserv: ds, 536 Maxlinks: 4, 537 } 538 539 spl := chunk.SizeSplitterGen(500) 540 541 blks, errs := chunk.Chan(spl(bytes.NewReader(data[:1]))) 542 543 ctx := context.Background() 544 nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) 545 if err != nil { 546 t.Fatal(err) 547 } 548 549 blks, errs = chunk.Chan(spl(bytes.NewReader(data[1:]))) 550 551 nnode, err = TrickleAppend(ctx, nnode, dbp.New(blks, errs)) 552 if err != nil { 553 t.Fatal(err) 554 } 555 556 fread, err := uio.NewDagReader(ctx, nnode, ds) 557 if err != nil { 558 t.Fatal(err) 559 } 560 561 out, err := ioutil.ReadAll(fread) 562 if err != nil { 563 t.Fatal(err) 564 } 565 566 fmt.Println(out, data) 567 err = arrComp(out, data) 568 if err != nil { 569 t.Fatal(err) 570 } 571 } 572 573 func printDag(nd *merkledag.Node, ds merkledag.DAGService, indent int) { 574 pbd, err := ft.FromBytes(nd.Data) 575 if err != nil { 576 panic(err) 577 } 578 579 for i := 0; i < indent; i++ { 580 fmt.Print(" ") 581 } 582 fmt.Printf("{size = %d, type = %s, nc = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes())) 583 if len(nd.Links) > 0 { 584 fmt.Println() 585 } 586 for _, lnk := range nd.Links { 587 child, err := lnk.GetNode(context.Background(), ds) 588 if err != nil { 589 panic(err) 590 } 591 printDag(child, ds, indent+1) 592 } 593 if len(nd.Links) > 0 { 594 for i := 0; i < indent; i++ { 595 fmt.Print(" ") 596 } 597 } 598 fmt.Println("}") 599 }