func TestSeekEndSingleBlockFile(t *testing.T) { nbytes := int64(100) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 5000)) if err != nil { t.Fatal(err) } rs, err := uio.NewDagReader(context.Background(), nd, ds) if err != nil { t.Fatal(err) } seeked, err := rs.Seek(0, os.SEEK_END) if err != nil { t.Fatal(err) } if seeked != nbytes { t.Fatal("Failed to seek to end") } }
func TestAppend(t *testing.T) { nbytes := int64(128 * 1024) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) // Reader for half the bytes read := bytes.NewReader(should[:nbytes/2]) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) if err != nil { t.Fatal(err) } dbp := &h.DagBuilderParams{ Dagserv: ds, Maxlinks: h.DefaultLinksPerBlock, } r := bytes.NewReader(should[nbytes/2:]) blks, errs := chunk.Chan(chunk.NewSizeSplitter(r, 500)) ctx := context.Background() nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) if err != nil { t.Fatal(err) } err = VerifyTrickleDagStructure(nnode, ds, dbp.Maxlinks, layerRepeat) if err != nil { t.Fatal(err) } fread, err := uio.NewDagReader(ctx, nnode, ds) if err != nil { t.Fatal(err) } out, err := ioutil.ReadAll(fread) if err != nil { t.Fatal(err) } err = arrComp(out, should) if err != nil { t.Fatal(err) } }
func getTrickleDag(t testing.TB, size int64, blksize int64) (*dag.Node, dag.DAGService) { ds := mdtest.Mock() r := io.LimitReader(u.NewTimeSeededRand(), size) nd, err := BuildTrickleDagFromReader(ds, chunk.NewSizeSplitter(r, blksize), nil) if err != nil { t.Fatal(err) } return nd, ds }
func getTestDag(t *testing.T, ds dag.DAGService, size int64, blksize int64) (*dag.Node, []byte) { data := make([]byte, size) u.NewTimeSeededRand().Read(data) r := bytes.NewReader(data) nd, err := buildTestDag(ds, chunk.NewSizeSplitter(r, blksize)) if err != nil { t.Fatal(err) } return nd, data }
// This test appends one byte at a time to an empty file func TestMultipleAppends(t *testing.T) { ds := mdtest.Mock() // TODO: fix small size appends and make this number bigger nbytes := int64(1000) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(nil) nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) if err != nil { t.Fatal(err) } dbp := &h.DagBuilderParams{ Dagserv: ds, Maxlinks: 4, } spl := chunk.SizeSplitterGen(500) ctx := context.Background() for i := 0; i < len(should); i++ { blks, errs := chunk.Chan(spl(bytes.NewReader(should[i : i+1]))) nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) if err != nil { t.Fatal(err) } err = VerifyTrickleDagStructure(nnode, ds, dbp.Maxlinks, layerRepeat) if err != nil { t.Fatal(err) } fread, err := uio.NewDagReader(ctx, nnode, ds) if err != nil { t.Fatal(err) } out, err := ioutil.ReadAll(fread) if err != nil { t.Fatal(err) } err = arrComp(out, should[:i+1]) if err != nil { t.Fatal(err) } } }
// expandSparse grows the file with zero blocks of 4096 // A small blocksize is chosen to aid in deduplication func (dm *DagModifier) expandSparse(size int64) error { r := io.LimitReader(zeroReader{}, size) spl := chunk.NewSizeSplitter(r, 4096) blks, errs := chunk.Chan(spl) nnode, err := dm.appendData(dm.curNode, blks, errs) if err != nil { return err } _, err = dm.dagserv.Add(nnode) if err != nil { return err } dm.curNode = nnode return nil }
// Builds a DAG from the given file, writing created blocks to disk as they are // created func BuildDagFromFile(fpath string, ds dag.DAGService, mp pin.ManualPinner) (*dag.Node, error) { stat, err := os.Lstat(fpath) if err != nil { return nil, err } if stat.IsDir() { return nil, fmt.Errorf("`%s` is a directory", fpath) } f, err := files.NewSerialFile(fpath, fpath, stat) if err != nil { return nil, err } defer f.Close() return BuildDagFromReader(ds, chunk.NewSizeSplitter(f, chunk.DefaultBlockSize), BasicPinnerCB(mp)) }
// Add builds a merkledag from the a reader, pinning all objects to the local // datastore. Returns a key representing the root node. func Add(n *core.IpfsNode, r io.Reader) (string, error) { // TODO more attractive function signature importer.BuildDagFromReader dagNode, err := importer.BuildDagFromReader( n.DAG, chunk.NewSizeSplitter(r, chunk.DefaultBlockSize), importer.BasicPinnerCB(n.Pinning.GetManual()), ) if err != nil { return "", err } k, err := dagNode.Key() if err != nil { return "", err } return k.String(), nil }
func TestSeekingStress(t *testing.T) { nbytes := int64(1024 * 1024) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 1000)) if err != nil { t.Fatal(err) } rs, err := uio.NewDagReader(context.Background(), nd, ds) if err != nil { t.Fatal(err) } testbuf := make([]byte, nbytes) for i := 0; i < 50; i++ { offset := mrand.Intn(int(nbytes)) l := int(nbytes) - offset n, err := rs.Seek(int64(offset), os.SEEK_SET) if err != nil { t.Fatal(err) } if n != int64(offset) { t.Fatal("Seek failed to move to correct position") } nread, err := rs.Read(testbuf[:l]) if err != nil { t.Fatal(err) } if nread != l { t.Fatal("Failed to read enough bytes") } err = arrComp(testbuf[:l], should[offset:offset+l]) if err != nil { t.Fatal(err) } } }
func TestSeekToAlmostBegin(t *testing.T) { nbytes := int64(10 * 1024) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) if err != nil { t.Fatal(err) } rs, err := uio.NewDagReader(context.Background(), nd, ds) if err != nil { t.Fatal(err) } n, err := io.CopyN(ioutil.Discard, rs, 1024*4) if err != nil { t.Fatal(err) } if n != 4096 { t.Fatal("Copy didnt copy enough bytes") } seeked, err := rs.Seek(1, os.SEEK_SET) if err != nil { t.Fatal(err) } if seeked != 1 { t.Fatal("Failed to seek to almost beginning") } out, err := ioutil.ReadAll(rs) if err != nil { t.Fatal(err) } err = arrComp(out, should[1:]) if err != nil { t.Fatal(err) } }
func TestSeekingConsistency(t *testing.T) { nbytes := int64(128 * 1024) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) if err != nil { t.Fatal(err) } rs, err := uio.NewDagReader(context.Background(), nd, ds) if err != nil { t.Fatal(err) } out := make([]byte, nbytes) for coff := nbytes - 4096; coff >= 0; coff -= 4096 { t.Log(coff) n, err := rs.Seek(coff, os.SEEK_SET) if err != nil { t.Fatal(err) } if n != coff { t.Fatal("wasnt able to seek to the right position") } nread, err := rs.Read(out[coff : coff+4096]) if err != nil { t.Fatal(err) } if nread != 4096 { t.Fatal("didnt read the correct number of bytes") } } err = arrComp(out, should) if err != nil { t.Fatal(err) } }
func TestSeekingBasic(t *testing.T) { nbytes := int64(10 * 1024) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(should) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 512)) if err != nil { t.Fatal(err) } rs, err := uio.NewDagReader(context.Background(), nd, ds) if err != nil { t.Fatal(err) } start := int64(4000) n, err := rs.Seek(start, os.SEEK_SET) if err != nil { t.Fatal(err) } if n != start { t.Fatal("Failed to seek to correct offset") } out, err := ioutil.ReadAll(rs) if err != nil { t.Fatal(err) } err = arrComp(out, should[start:]) if err != nil { t.Fatal(err) } }
func sizeSplitterGen(size int64) chunk.SplitterGen { return func(r io.Reader) chunk.Splitter { return chunk.NewSizeSplitter(r, size) } }
func runBatchFetchTest(t *testing.T, read io.Reader) { ctx := context.Background() var dagservs []DAGService for _, bsi := range bstest.Mocks(5) { dagservs = append(dagservs, NewDAGService(bsi)) } spl := chunk.NewSizeSplitter(read, 512) root, err := imp.BuildDagFromReader(dagservs[0], spl, nil) if err != nil { t.Fatal(err) } t.Log("finished setup.") dagr, err := uio.NewDagReader(ctx, root, dagservs[0]) if err != nil { t.Fatal(err) } expected, err := ioutil.ReadAll(dagr) if err != nil { t.Fatal(err) } err = dagservs[0].AddRecursive(root) if err != nil { t.Fatal(err) } t.Log("Added file to first node.") k, err := root.Key() if err != nil { t.Fatal(err) } wg := sync.WaitGroup{} for i := 1; i < len(dagservs); i++ { wg.Add(1) go func(i int) { defer wg.Done() first, err := dagservs[i].Get(ctx, k) if err != nil { t.Fatal(err) } fmt.Println("Got first node back.") read, err := uio.NewDagReader(ctx, first, dagservs[i]) if err != nil { t.Fatal(err) } datagot, err := ioutil.ReadAll(read) if err != nil { t.Fatal(err) } if !bytes.Equal(datagot, expected) { t.Fatal("Got bad data back!") } }(i) } wg.Wait() }