Commit 0aefa5b1 authored by Masih H. Derkani's avatar Masih H. Derkani Committed by Daniel Martí

Implement examples and tests for `index` package

Add examples that show how to read and write an index to/from file.

Test marshalling and unmarshalling index files.

Run `gofumt` on repo.
parent 7d8f54ff
......@@ -2,13 +2,14 @@ package blockstore
import (
"context"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/ipfs/go-merkledag"
"io"
"os"
"testing"
"time"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/ipfs/go-merkledag"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
......
package index_test
import (
"fmt"
"os"
"reflect"
carv2 "github.com/ipld/go-car/v2"
"github.com/ipld/go-car/v2/index"
)
// ExampleReadFrom unmarshalls an index from an indexed CARv2 file, and for each root CID prints the
// offset at which its corresponding block starts relative to the wrapped CARv1 data payload.
func ExampleReadFrom() {
// Open the CARv2 file
cr, err := carv2.OpenReader("../testdata/sample-wrapped-v2.car")
if err != nil {
panic(err)
}
defer cr.Close()
// Get root CIDs in the CARv1 file.
roots, err := cr.Roots()
if err != nil {
panic(err)
}
// Read and unmarshall index within CARv2 file.
idx, err := index.ReadFrom(cr.IndexReader())
if err != nil {
panic(err)
}
// For each root CID print the offset relative to CARv1 data payload.
for _, r := range roots {
offset, err := idx.Get(r)
if err != nil {
panic(err)
}
fmt.Printf("Frame with CID %v starts at offset %v relative to CARv1 data payload.\n", r, offset)
}
// Output:
// Frame with CID bafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy starts at offset 61 relative to CARv1 data payload.
}
// ExampleSave unmarshalls an index from an indexed CARv2 file, and stores it as a separate
// file on disk.
func ExampleSave() {
// Open the CARv2 file
src := "../testdata/sample-wrapped-v2.car"
cr, err := carv2.OpenReader(src)
if err != nil {
panic(err)
}
defer cr.Close()
// Read and unmarshall index within CARv2 file.
idx, err := index.ReadFrom(cr.IndexReader())
if err != nil {
panic(err)
}
// Store the index alone onto destination file.
dest := "../testdata/sample-index.carindex"
err = index.Save(idx, dest)
if err != nil {
panic(err)
}
// Open the destination file that contains the index only.
f, err := os.Open(dest)
if err != nil {
panic(err)
}
defer f.Close()
// Read and unmarshall the destination file as a separate index instance.
reReadIdx, err := index.ReadFrom(f)
if err != nil {
panic(err)
}
// Expect indices to be equal.
if reflect.DeepEqual(idx, reReadIdx) {
fmt.Printf("Saved index file at %v matches the index embedded in CARv2 at %v.\n", dest, src)
} else {
panic("expected to get the same index as the CARv2 file")
}
// Output:
// Saved index file at ../testdata/sample-index.carindex matches the index embedded in CARv2 at ../testdata/sample-wrapped-v2.car.
}
package index
import (
"bytes"
"io"
"os"
"path/filepath"
"testing"
blocks "github.com/ipfs/go-block-format"
"github.com/ipld/go-car/v2/internal/carv1"
"github.com/ipld/go-car/v2/internal/carv1/util"
"github.com/multiformats/go-multicodec"
"github.com/multiformats/go-varint"
"github.com/stretchr/testify/require"
)
func TestNew(t *testing.T) {
tests := []struct {
name string
codec multicodec.Code
want Index
wantErr bool
}{
{
name: "CarSortedIndexCodecIsConstructed",
codec: multicodec.CarIndexSorted,
want: newSorted(),
},
{
name: "ValidMultiCodecButUnknwonToIndexIsError",
codec: multicodec.Cidv1,
wantErr: true,
},
{
name: "IndexSingleSortedMultiCodecIsError",
codec: multicodec.Code(indexSingleSorted),
wantErr: true,
},
{
name: "IndexHashedMultiCodecIsError",
codec: multicodec.Code(indexHashed),
wantErr: true,
},
{
name: "IndexGobHashedMultiCodecIsError",
codec: multicodec.Code(indexGobHashed),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := New(tt.codec)
if tt.wantErr {
require.Error(t, err)
} else {
require.Equal(t, tt.want, got)
}
})
}
}
func TestReadFrom(t *testing.T) {
idxf, err := os.Open("../testdata/sample-index.carindex")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, idxf.Close()) })
subject, err := ReadFrom(idxf)
require.NoError(t, err)
crf, err := os.Open("../testdata/sample-v1.car")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, crf.Close()) })
cr, err := carv1.NewCarReader(crf)
require.NoError(t, err)
for {
wantBlock, err := cr.Next()
if err == io.EOF {
break
}
require.NoError(t, err)
// Get offset from the index for a CID and assert it exists
gotOffset, err := subject.Get(wantBlock.Cid())
require.NoError(t, err)
require.NotZero(t, gotOffset)
// Seek to the offset on CARv1 file
_, err = crf.Seek(int64(gotOffset), io.SeekStart)
require.NoError(t, err)
// Read the fame at offset and assert the frame corresponds to the expected block.
gotCid, gotData, err := util.ReadNode(crf)
require.NoError(t, err)
gotBlock, err := blocks.NewBlockWithCid(gotData, gotCid)
require.NoError(t, err)
require.Equal(t, wantBlock, gotBlock)
}
}
func TestWriteTo(t *testing.T) {
// Read sample index on file
idxf, err := os.Open("../testdata/sample-index.carindex")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, idxf.Close()) })
// Unmarshall to get expected index
wantIdx, err := ReadFrom(idxf)
require.NoError(t, err)
// Write the same index out
dest := filepath.Join(t.TempDir(), "index-write-to-test.carindex")
destF, err := os.Create(dest)
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, destF.Close()) })
require.NoError(t, WriteTo(wantIdx, destF))
// Seek to the beginning of the written out file.
_, err = destF.Seek(0, io.SeekStart)
require.NoError(t, err)
// Read the written index back
gotIdx, err := ReadFrom(destF)
require.NoError(t, err)
// Assert they are equal
require.Equal(t, wantIdx, gotIdx)
}
func TestSave(t *testing.T) {
// Read sample index on file
idxf, err := os.Open("../testdata/sample-index.carindex")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, idxf.Close()) })
// Unmarshall to get expected index
wantIdx, err := ReadFrom(idxf)
require.NoError(t, err)
// Save the same index at destination
dest := filepath.Join(t.TempDir(), "index-write-to-test.carindex")
require.NoError(t, Save(wantIdx, dest))
// Open the saved file
destF, err := os.Open(dest)
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, destF.Close()) })
// Read the written index back
gotIdx, err := ReadFrom(destF)
require.NoError(t, err)
// Assert they are equal
require.Equal(t, wantIdx, gotIdx)
}
func TestMarshalledIndexStartsWithCodec(t *testing.T) {
// Read sample index on file
idxf, err := os.Open("../testdata/sample-index.carindex")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, idxf.Close()) })
// Unmarshall to get expected index
wantIdx, err := ReadFrom(idxf)
require.NoError(t, err)
// Assert the first two bytes are the corresponding multicodec code.
buf := new(bytes.Buffer)
require.NoError(t, WriteTo(wantIdx, buf))
require.Equal(t, varint.ToUvarint(uint64(multicodec.CarIndexSorted)), buf.Bytes()[:2])
}
package index
import (
"testing"
"github.com/ipfs/go-merkledag"
"github.com/multiformats/go-multicodec"
"github.com/stretchr/testify/require"
"testing"
)
func TestSortedIndexCodec(t *testing.T) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment