| 1 | package tests |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "math" |
| 6 | "strings" |
| 7 | "testing" |
| 8 | |
| 9 | "github.com/ipfs/boxo/path" |
| 10 | "github.com/ipfs/go-cid" |
| 11 | ipldcbor "github.com/ipfs/go-ipld-cbor" |
| 12 | "github.com/ipfs/kubo/core/coreiface/options" |
| 13 | "github.com/stretchr/testify/require" |
| 14 | ) |
| 15 | |
| 16 | func newIPLDPath(t *testing.T, cid cid.Cid) path.ImmutablePath { |
| 17 | p, err := path.NewPath(fmt.Sprintf("/%s/%s", path.IPLDNamespace, cid.String())) |
| 18 | require.NoError(t, err) |
| 19 | im, err := path.NewImmutablePath(p) |
| 20 | require.NoError(t, err) |
| 21 | return im |
| 22 | } |
| 23 | |
| 24 | func (tp *TestSuite) TestPath(t *testing.T) { |
| 25 | t.Run("TestMutablePath", tp.TestMutablePath) |
| 26 | t.Run("TestPathRemainder", tp.TestPathRemainder) |
| 27 | t.Run("TestEmptyPathRemainder", tp.TestEmptyPathRemainder) |
| 28 | t.Run("TestInvalidPathRemainder", tp.TestInvalidPathRemainder) |
| 29 | t.Run("TestPathRoot", tp.TestPathRoot) |
| 30 | t.Run("TestPathJoin", tp.TestPathJoin) |
| 31 | } |
| 32 | |
| 33 | func (tp *TestSuite) TestMutablePath(t *testing.T) { |
| 34 | ctx := t.Context() |
| 35 | |
| 36 | api, err := tp.makeAPI(t, ctx) |
| 37 | require.NoError(t, err) |
| 38 | |
| 39 | blk, err := api.Block().Put(ctx, strings.NewReader(`foo`)) |
| 40 | require.NoError(t, err) |
| 41 | require.False(t, blk.Path().Mutable()) |
| 42 | require.NotNil(t, api.Key()) |
| 43 | |
| 44 | keys, err := api.Key().List(ctx) |
| 45 | require.NoError(t, err) |
| 46 | require.True(t, keys[0].Path().Mutable()) |
| 47 | } |
| 48 | |
| 49 | func (tp *TestSuite) TestPathRemainder(t *testing.T) { |
| 50 | ctx := t.Context() |
| 51 | |
| 52 | api, err := tp.makeAPI(t, ctx) |
| 53 | require.NoError(t, err) |
| 54 | require.NotNil(t, api.Dag()) |
| 55 | |
| 56 | nd, err := ipldcbor.FromJSON(strings.NewReader(`{"foo": {"bar": "baz"}}`), math.MaxUint64, -1) |
| 57 | require.NoError(t, err) |
| 58 | |
| 59 | err = api.Dag().Add(ctx, nd) |
| 60 | require.NoError(t, err) |
| 61 | |
| 62 | p, err := path.Join(path.FromCid(nd.Cid()), "foo", "bar") |
| 63 | require.NoError(t, err) |
| 64 | |
| 65 | _, remainder, err := api.ResolvePath(ctx, p) |
| 66 | require.NoError(t, err) |
| 67 | require.Equal(t, "/foo/bar", path.SegmentsToString(remainder...)) |
| 68 | } |
| 69 | |
| 70 | func (tp *TestSuite) TestEmptyPathRemainder(t *testing.T) { |
| 71 | ctx := t.Context() |
| 72 | |
| 73 | api, err := tp.makeAPI(t, ctx) |
| 74 | require.NoError(t, err) |
| 75 | require.NotNil(t, api.Dag()) |
| 76 | |
| 77 | nd, err := ipldcbor.FromJSON(strings.NewReader(`{"foo": {"bar": "baz"}}`), math.MaxUint64, -1) |
| 78 | require.NoError(t, err) |
| 79 | |
| 80 | err = api.Dag().Add(ctx, nd) |
| 81 | require.NoError(t, err) |
| 82 | |
| 83 | _, remainder, err := api.ResolvePath(ctx, path.FromCid(nd.Cid())) |
| 84 | require.NoError(t, err) |
| 85 | require.Empty(t, remainder) |
| 86 | } |
| 87 | |
| 88 | func (tp *TestSuite) TestInvalidPathRemainder(t *testing.T) { |
| 89 | ctx := t.Context() |
| 90 | |
| 91 | api, err := tp.makeAPI(t, ctx) |
| 92 | require.NoError(t, err) |
| 93 | require.NotNil(t, api.Dag()) |
| 94 | |
| 95 | nd, err := ipldcbor.FromJSON(strings.NewReader(`{"foo": {"bar": "baz"}}`), math.MaxUint64, -1) |
| 96 | require.NoError(t, err) |
| 97 | |
| 98 | err = api.Dag().Add(ctx, nd) |
| 99 | require.NoError(t, err) |
| 100 | |
| 101 | p, err := path.Join(newIPLDPath(t, nd.Cid()), "/bar/baz") |
| 102 | require.NoError(t, err) |
| 103 | |
| 104 | _, _, err = api.ResolvePath(ctx, p) |
| 105 | require.NotNil(t, err) |
| 106 | require.ErrorContains(t, err, `no link named "bar"`) |
| 107 | } |
| 108 | |
| 109 | func (tp *TestSuite) TestPathRoot(t *testing.T) { |
| 110 | ctx := t.Context() |
| 111 | |
| 112 | api, err := tp.makeAPI(t, ctx) |
| 113 | require.NoError(t, err) |
| 114 | require.NotNil(t, api.Block()) |
| 115 | |
| 116 | blk, err := api.Block().Put(ctx, strings.NewReader(`foo`), options.Block.Format("raw")) |
| 117 | require.NoError(t, err) |
| 118 | require.NotNil(t, api.Dag()) |
| 119 | |
| 120 | nd, err := ipldcbor.FromJSON(strings.NewReader(`{"foo": {"/": "`+blk.Path().RootCid().String()+`"}}`), math.MaxUint64, -1) |
| 121 | require.NoError(t, err) |
| 122 | |
| 123 | err = api.Dag().Add(ctx, nd) |
| 124 | require.NoError(t, err) |
| 125 | |
| 126 | p, err := path.Join(newIPLDPath(t, nd.Cid()), "/foo") |
| 127 | require.NoError(t, err) |
| 128 | |
| 129 | rp, _, err := api.ResolvePath(ctx, p) |
| 130 | require.NoError(t, err) |
| 131 | require.Equal(t, rp.RootCid().String(), blk.Path().RootCid().String()) |
| 132 | } |
| 133 | |
| 134 | func (tp *TestSuite) TestPathJoin(t *testing.T) { |
| 135 | p1, err := path.NewPath("/ipfs/QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6/bar/baz") |
| 136 | require.NoError(t, err) |
| 137 | |
| 138 | p2, err := path.Join(p1, "foo") |
| 139 | require.NoError(t, err) |
| 140 | |
| 141 | require.Equal(t, "/ipfs/QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6/bar/baz/foo", p2.String()) |
| 142 | } |