github.com/storacha/go-ucanto@v0.7.2/core/car/car_test.go (about) 1 package car 2 3 import ( 4 "bytes" 5 "io" 6 "os" 7 "testing" 8 9 "github.com/ipfs/go-cid" 10 cidlink "github.com/ipld/go-ipld-prime/linking/cid" 11 "github.com/storacha/go-ucanto/core/ipld" 12 ) 13 14 type fixture struct { 15 path string 16 root ipld.Link 17 blocks []ipld.Link 18 } 19 20 var fixtures = []fixture{ 21 { 22 path: "testdata/lost-dog.jpg.car", 23 root: cidlink.Link{Cid: cid.MustParse("bafybeif4owy5gno5lwnixqm52rwqfodklf76hsetxdhffuxnplvijskzqq")}, 24 blocks: []ipld.Link{ 25 cidlink.Link{Cid: cid.MustParse("bafkreifau35r7vi37tvbvfy3hdwvgb4tlflqf7zcdzeujqcjk3rsphiwte")}, 26 cidlink.Link{Cid: cid.MustParse("bafkreicj3ozpzd46nx26hflpoi6hgm5linwo65cvphd5ol3ke3vk5nb7aa")}, 27 cidlink.Link{Cid: cid.MustParse("bafybeihkqv2ukwgpgzkwsuz7whmvneztvxglkljbs3zosewgku2cfluvba")}, 28 cidlink.Link{Cid: cid.MustParse("bafybeif4owy5gno5lwnixqm52rwqfodklf76hsetxdhffuxnplvijskzqq")}, 29 }, 30 }, 31 } 32 33 func TestDecodeCAR(t *testing.T) { 34 file, err := os.Open(fixtures[0].path) 35 if err != nil { 36 t.Fatal(err) 37 } 38 39 roots, blocks, err := Decode(file) 40 if err != nil { 41 t.Fatal(err) 42 } 43 if len(roots) != 1 { 44 t.Fatalf("unexpected number of roots: %d, expected: 1", len(roots)) 45 } 46 if roots[0].String() != fixtures[0].root.String() { 47 t.Fatalf("unexpected root: %s, expected: %s", roots[0], fixtures[0].root) 48 } 49 50 var blks []CarBlock 51 for b, err := range blocks { 52 if err != nil { 53 t.Fatalf("reading blocks: %s", err) 54 } 55 cb, ok := b.(CarBlock) 56 if !ok { 57 t.Fatalf("should have returned a car block") 58 } 59 blks = append(blks, cb) 60 } 61 62 if len(blks) != len(fixtures[0].blocks) { 63 t.Fatalf("incorrect number of blocks: %d, expected: %d", len(blks), len(fixtures[0].blocks)) 64 } 65 for i, b := range fixtures[0].blocks { 66 if b.String() != blks[i].Link().String() { 67 t.Fatalf("unexpected block: %s, expected: %s", b, blks[i].Link()) 68 } 69 // verify offset and length can be used to directly read the block in the CAR file 70 file.Seek(int64(blks[i].Offset()), io.SeekStart) 71 data := make([]byte, blks[i].Length()) 72 _, err := file.Read(data) 73 if err != nil { 74 t.Fatalf("error reading block from raw file") 75 } 76 hashed, err := blks[i].Link().(cidlink.Link).Cid.Prefix().Sum(data) 77 if err != nil { 78 t.Fatalf("error hashing block from raw file") 79 } 80 81 if hashed.String() != blks[i].Link().String() { 82 t.Fatalf("raw read from offset block: %s, expected: %s", hashed, blks[i].Link()) 83 } 84 85 } 86 } 87 88 func TestEncodeCAR(t *testing.T) { 89 file, err := os.Open(fixtures[0].path) 90 if err != nil { 91 t.Fatal(err) 92 } 93 94 fbytes, err := io.ReadAll(file) 95 if err != nil { 96 t.Fatal(err) 97 } 98 99 roots, blocks, err := Decode(bytes.NewReader(fbytes)) 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 rd := Encode(roots, blocks) 105 106 dbytes, err := io.ReadAll(rd) 107 if err != nil { 108 t.Fatal(err) 109 } 110 111 if !bytes.Equal(fbytes, dbytes) { 112 t.Fatal("failed to round trip") 113 } 114 }