github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/importer/balanced/balanced_test.go (about)

     1  package balanced
     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  	dag "github.com/ipfs/go-ipfs/merkledag"
    16  	mdtest "github.com/ipfs/go-ipfs/merkledag/test"
    17  	pin "github.com/ipfs/go-ipfs/pin"
    18  	uio "github.com/ipfs/go-ipfs/unixfs/io"
    19  	u "github.com/ipfs/go-ipfs/util"
    20  )
    21  
    22  // TODO: extract these tests and more as a generic layout test suite
    23  
    24  func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) {
    25  	// Start the splitter
    26  	blkch, errs := chunk.Chan(spl)
    27  
    28  	dbp := h.DagBuilderParams{
    29  		Dagserv:  ds,
    30  		Maxlinks: h.DefaultLinksPerBlock,
    31  	}
    32  
    33  	return BalancedLayout(dbp.New(blkch, errs))
    34  }
    35  
    36  func getTestDag(t *testing.T, ds dag.DAGService, size int64, blksize int64) (*dag.Node, []byte) {
    37  	data := make([]byte, size)
    38  	u.NewTimeSeededRand().Read(data)
    39  	r := bytes.NewReader(data)
    40  
    41  	nd, err := buildTestDag(ds, chunk.NewSizeSplitter(r, blksize))
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  
    46  	return nd, data
    47  }
    48  
    49  //Test where calls to read are smaller than the chunk size
    50  func TestSizeBasedSplit(t *testing.T) {
    51  	if testing.Short() {
    52  		t.SkipNow()
    53  	}
    54  
    55  	bs := chunk.SizeSplitterGen(512)
    56  	testFileConsistency(t, bs, 32*512)
    57  	bs = chunk.SizeSplitterGen(4096)
    58  	testFileConsistency(t, bs, 32*4096)
    59  
    60  	// Uneven offset
    61  	testFileConsistency(t, bs, 31*4095)
    62  }
    63  
    64  func dup(b []byte) []byte {
    65  	o := make([]byte, len(b))
    66  	copy(o, b)
    67  	return o
    68  }
    69  
    70  func testFileConsistency(t *testing.T, bs chunk.SplitterGen, nbytes int) {
    71  	should := make([]byte, nbytes)
    72  	u.NewTimeSeededRand().Read(should)
    73  
    74  	read := bytes.NewReader(should)
    75  	ds := mdtest.Mock()
    76  	nd, err := buildTestDag(ds, bs(read))
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	r, err := uio.NewDagReader(context.Background(), nd, ds)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	out, err := ioutil.ReadAll(r)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	err = arrComp(out, should)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  }
    96  
    97  func TestBuilderConsistency(t *testing.T) {
    98  	dagserv := mdtest.Mock()
    99  	nd, should := getTestDag(t, dagserv, 100000, chunk.DefaultBlockSize)
   100  
   101  	r, err := uio.NewDagReader(context.Background(), nd, dagserv)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	out, err := ioutil.ReadAll(r)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  
   111  	err = arrComp(out, should)
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  }
   116  
   117  func arrComp(a, b []byte) error {
   118  	if len(a) != len(b) {
   119  		return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b))
   120  	}
   121  	for i, v := range a {
   122  		if v != b[i] {
   123  			return fmt.Errorf("Arrays differ at index: %d", i)
   124  		}
   125  	}
   126  	return nil
   127  }
   128  
   129  type dagservAndPinner struct {
   130  	ds dag.DAGService
   131  	mp pin.ManualPinner
   132  }
   133  
   134  func TestIndirectBlocks(t *testing.T) {
   135  	ds := mdtest.Mock()
   136  	dag, buf := getTestDag(t, ds, 1024*1024, 512)
   137  
   138  	reader, err := uio.NewDagReader(context.Background(), dag, ds)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  
   143  	out, err := ioutil.ReadAll(reader)
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  
   148  	if !bytes.Equal(out, buf) {
   149  		t.Fatal("Not equal!")
   150  	}
   151  }
   152  
   153  func TestSeekingBasic(t *testing.T) {
   154  	nbytes := int64(10 * 1024)
   155  	ds := mdtest.Mock()
   156  	nd, should := getTestDag(t, ds, nbytes, 500)
   157  
   158  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  
   163  	start := int64(4000)
   164  	n, err := rs.Seek(start, os.SEEK_SET)
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  	if n != start {
   169  		t.Fatal("Failed to seek to correct offset")
   170  	}
   171  
   172  	out, err := ioutil.ReadAll(rs)
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	err = arrComp(out, should[start:])
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  }
   182  
   183  func TestSeekToBegin(t *testing.T) {
   184  	ds := mdtest.Mock()
   185  	nd, should := getTestDag(t, ds, 10*1024, 500)
   186  
   187  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  
   192  	n, err := io.CopyN(ioutil.Discard, rs, 1024*4)
   193  	if err != nil {
   194  		t.Fatal(err)
   195  	}
   196  	if n != 4096 {
   197  		t.Fatal("Copy didnt copy enough bytes")
   198  	}
   199  
   200  	seeked, err := rs.Seek(0, os.SEEK_SET)
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  	if seeked != 0 {
   205  		t.Fatal("Failed to seek to beginning")
   206  	}
   207  
   208  	out, err := ioutil.ReadAll(rs)
   209  	if err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	err = arrComp(out, should)
   214  	if err != nil {
   215  		t.Fatal(err)
   216  	}
   217  }
   218  
   219  func TestSeekToAlmostBegin(t *testing.T) {
   220  	ds := mdtest.Mock()
   221  	nd, should := getTestDag(t, ds, 10*1024, 500)
   222  
   223  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  
   228  	n, err := io.CopyN(ioutil.Discard, rs, 1024*4)
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  	if n != 4096 {
   233  		t.Fatal("Copy didnt copy enough bytes")
   234  	}
   235  
   236  	seeked, err := rs.Seek(1, os.SEEK_SET)
   237  	if err != nil {
   238  		t.Fatal(err)
   239  	}
   240  	if seeked != 1 {
   241  		t.Fatal("Failed to seek to almost beginning")
   242  	}
   243  
   244  	out, err := ioutil.ReadAll(rs)
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  
   249  	err = arrComp(out, should[1:])
   250  	if err != nil {
   251  		t.Fatal(err)
   252  	}
   253  }
   254  
   255  func TestSeekEnd(t *testing.T) {
   256  	nbytes := int64(50 * 1024)
   257  	ds := mdtest.Mock()
   258  	nd, _ := getTestDag(t, ds, nbytes, 500)
   259  
   260  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   261  	if err != nil {
   262  		t.Fatal(err)
   263  	}
   264  
   265  	seeked, err := rs.Seek(0, os.SEEK_END)
   266  	if err != nil {
   267  		t.Fatal(err)
   268  	}
   269  	if seeked != nbytes {
   270  		t.Fatal("Failed to seek to end")
   271  	}
   272  }
   273  
   274  func TestSeekEndSingleBlockFile(t *testing.T) {
   275  	nbytes := int64(100)
   276  	ds := mdtest.Mock()
   277  	nd, _ := getTestDag(t, ds, nbytes, 5000)
   278  
   279  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   280  	if err != nil {
   281  		t.Fatal(err)
   282  	}
   283  
   284  	seeked, err := rs.Seek(0, os.SEEK_END)
   285  	if err != nil {
   286  		t.Fatal(err)
   287  	}
   288  	if seeked != nbytes {
   289  		t.Fatal("Failed to seek to end")
   290  	}
   291  }
   292  
   293  func TestSeekingStress(t *testing.T) {
   294  	nbytes := int64(1024 * 1024)
   295  	ds := mdtest.Mock()
   296  	nd, should := getTestDag(t, ds, nbytes, 1000)
   297  
   298  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  
   303  	testbuf := make([]byte, nbytes)
   304  	for i := 0; i < 50; i++ {
   305  		offset := mrand.Intn(int(nbytes))
   306  		l := int(nbytes) - offset
   307  		n, err := rs.Seek(int64(offset), os.SEEK_SET)
   308  		if err != nil {
   309  			t.Fatal(err)
   310  		}
   311  		if n != int64(offset) {
   312  			t.Fatal("Seek failed to move to correct position")
   313  		}
   314  
   315  		nread, err := rs.Read(testbuf[:l])
   316  		if err != nil {
   317  			t.Fatal(err)
   318  		}
   319  		if nread != l {
   320  			t.Fatal("Failed to read enough bytes")
   321  		}
   322  
   323  		err = arrComp(testbuf[:l], should[offset:offset+l])
   324  		if err != nil {
   325  			t.Fatal(err)
   326  		}
   327  	}
   328  
   329  }
   330  
   331  func TestSeekingConsistency(t *testing.T) {
   332  	nbytes := int64(128 * 1024)
   333  	ds := mdtest.Mock()
   334  	nd, should := getTestDag(t, ds, nbytes, 500)
   335  
   336  	rs, err := uio.NewDagReader(context.Background(), nd, ds)
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  
   341  	out := make([]byte, nbytes)
   342  
   343  	for coff := nbytes - 4096; coff >= 0; coff -= 4096 {
   344  		t.Log(coff)
   345  		n, err := rs.Seek(coff, os.SEEK_SET)
   346  		if err != nil {
   347  			t.Fatal(err)
   348  		}
   349  		if n != coff {
   350  			t.Fatal("wasnt able to seek to the right position")
   351  		}
   352  		nread, err := rs.Read(out[coff : coff+4096])
   353  		if err != nil {
   354  			t.Fatal(err)
   355  		}
   356  		if nread != 4096 {
   357  			t.Fatal("didnt read the correct number of bytes")
   358  		}
   359  	}
   360  
   361  	err = arrComp(out, should)
   362  	if err != nil {
   363  		t.Fatal(err)
   364  	}
   365  }