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 }