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  }