master
go 349 lines 7.94 KB
Raw
1 package tests
2
3 import (
4 "bytes"
5 "io"
6 "strings"
7 "testing"
8
9 "github.com/ipfs/boxo/path"
10 ipld "github.com/ipfs/go-ipld-format"
11 coreiface "github.com/ipfs/kubo/core/coreiface"
12 opt "github.com/ipfs/kubo/core/coreiface/options"
13 mh "github.com/multiformats/go-multihash"
14 )
15
16 var (
17 pbCidV0 = "QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN" // dag-pb
18 pbCid = "bafybeiffndsajwhk3lwjewwdxqntmjm4b5wxaaanokonsggenkbw6slwk4" // dag-pb
19 rawCid = "bafkreiffndsajwhk3lwjewwdxqntmjm4b5wxaaanokonsggenkbw6slwk4" // raw bytes
20 cborCid = "bafyreicnga62zhxnmnlt6ymq5hcbsg7gdhqdu6z4ehu3wpjhvqnflfy6nm" // dag-cbor
21 cborKCid = "bafyr2qgsohbwdlk7ajmmbb4lhoytmest4wdbe5xnexfvtxeatuyqqmwv3fgxp3pmhpc27gwey2cct56gloqefoqwcf3yqiqzsaqb7p4jefhcw" // dag-cbor keccak-512
22 )
23
24 // dag-pb
25 func pbBlock() io.Reader {
26 return bytes.NewReader([]byte{10, 12, 8, 2, 18, 6, 104, 101, 108, 108, 111, 10, 24, 6})
27 }
28
29 // dag-cbor
30 func cborBlock() io.Reader {
31 return bytes.NewReader([]byte{101, 72, 101, 108, 108, 111})
32 }
33
34 func (tp *TestSuite) TestBlock(t *testing.T) {
35 tp.hasApi(t, func(api coreiface.CoreAPI) error {
36 if api.Block() == nil {
37 return errAPINotImplemented
38 }
39 return nil
40 })
41
42 t.Run("TestBlockPut (get raw CIDv1)", tp.TestBlockPut)
43 t.Run("TestBlockPutCidCodec: dag-pb", tp.TestBlockPutCidCodecDagPb)
44 t.Run("TestBlockPutCidCodec: dag-cbor", tp.TestBlockPutCidCodecDagCbor)
45 t.Run("TestBlockPutFormat (legacy): cbor → dag-cbor", tp.TestBlockPutFormatDagCbor)
46 t.Run("TestBlockPutFormat (legacy): protobuf → dag-pb", tp.TestBlockPutFormatDagPb)
47 t.Run("TestBlockPutFormat (legacy): v0 → CIDv0", tp.TestBlockPutFormatV0)
48 t.Run("TestBlockPutHash", tp.TestBlockPutHash)
49 t.Run("TestBlockGet", tp.TestBlockGet)
50 t.Run("TestBlockRm", tp.TestBlockRm)
51 t.Run("TestBlockStat", tp.TestBlockStat)
52 t.Run("TestBlockPin", tp.TestBlockPin)
53 }
54
55 // when no opts are passed, produced CID has 'raw' codec
56 func (tp *TestSuite) TestBlockPut(t *testing.T) {
57 ctx := t.Context()
58 api, err := tp.makeAPI(t, ctx)
59 if err != nil {
60 t.Fatal(err)
61 }
62
63 res, err := api.Block().Put(ctx, pbBlock())
64 if err != nil {
65 t.Fatal(err)
66 }
67
68 if res.Path().RootCid().String() != rawCid {
69 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
70 }
71 }
72
73 // Format is deprecated, it used invalid codec names.
74 // Confirm 'cbor' gets fixed to 'dag-cbor'
75 func (tp *TestSuite) TestBlockPutFormatDagCbor(t *testing.T) {
76 ctx := t.Context()
77 api, err := tp.makeAPI(t, ctx)
78 if err != nil {
79 t.Fatal(err)
80 }
81
82 res, err := api.Block().Put(ctx, cborBlock(), opt.Block.Format("cbor"))
83 if err != nil {
84 t.Fatal(err)
85 }
86
87 if res.Path().RootCid().String() != cborCid {
88 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
89 }
90 }
91
92 // Format is deprecated, it used invalid codec names.
93 // Confirm 'protobuf' got fixed to 'dag-pb'
94 func (tp *TestSuite) TestBlockPutFormatDagPb(t *testing.T) {
95 ctx := t.Context()
96 api, err := tp.makeAPI(t, ctx)
97 if err != nil {
98 t.Fatal(err)
99 }
100
101 res, err := api.Block().Put(ctx, pbBlock(), opt.Block.Format("protobuf"))
102 if err != nil {
103 t.Fatal(err)
104 }
105
106 if res.Path().RootCid().String() != pbCid {
107 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
108 }
109 }
110
111 // Format is deprecated, it used invalid codec names.
112 // Confirm fake codec 'v0' got fixed to CIDv0 (with implicit dag-pb codec)
113 func (tp *TestSuite) TestBlockPutFormatV0(t *testing.T) {
114 ctx := t.Context()
115 api, err := tp.makeAPI(t, ctx)
116 if err != nil {
117 t.Fatal(err)
118 }
119
120 res, err := api.Block().Put(ctx, pbBlock(), opt.Block.Format("v0"))
121 if err != nil {
122 t.Fatal(err)
123 }
124
125 if res.Path().RootCid().String() != pbCidV0 {
126 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
127 }
128 }
129
130 func (tp *TestSuite) TestBlockPutCidCodecDagCbor(t *testing.T) {
131 ctx := t.Context()
132 api, err := tp.makeAPI(t, ctx)
133 if err != nil {
134 t.Fatal(err)
135 }
136
137 res, err := api.Block().Put(ctx, cborBlock(), opt.Block.CidCodec("dag-cbor"))
138 if err != nil {
139 t.Fatal(err)
140 }
141
142 if res.Path().RootCid().String() != cborCid {
143 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
144 }
145 }
146
147 func (tp *TestSuite) TestBlockPutCidCodecDagPb(t *testing.T) {
148 ctx := t.Context()
149 api, err := tp.makeAPI(t, ctx)
150 if err != nil {
151 t.Fatal(err)
152 }
153
154 res, err := api.Block().Put(ctx, pbBlock(), opt.Block.CidCodec("dag-pb"))
155 if err != nil {
156 t.Fatal(err)
157 }
158
159 if res.Path().RootCid().String() != pbCid {
160 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
161 }
162 }
163
164 func (tp *TestSuite) TestBlockPutHash(t *testing.T) {
165 ctx := t.Context()
166 api, err := tp.makeAPI(t, ctx)
167 if err != nil {
168 t.Fatal(err)
169 }
170
171 res, err := api.Block().Put(
172 ctx,
173 cborBlock(),
174 opt.Block.Hash(mh.KECCAK_512, -1),
175 opt.Block.CidCodec("dag-cbor"),
176 )
177 if err != nil {
178 t.Fatal(err)
179 }
180
181 if res.Path().RootCid().String() != cborKCid {
182 t.Errorf("got wrong cid: %s", res.Path().RootCid().String())
183 }
184 }
185
186 func (tp *TestSuite) TestBlockGet(t *testing.T) {
187 ctx := t.Context()
188 api, err := tp.makeAPI(t, ctx)
189 if err != nil {
190 t.Fatal(err)
191 }
192
193 res, err := api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Format("raw"))
194 if err != nil {
195 t.Fatal(err)
196 }
197
198 r, err := api.Block().Get(ctx, res.Path())
199 if err != nil {
200 t.Fatal(err)
201 }
202
203 d, err := io.ReadAll(r)
204 if err != nil {
205 t.Fatal(err)
206 }
207
208 if string(d) != "Hello" {
209 t.Error("didn't get correct data back")
210 }
211
212 p := path.FromCid(res.Path().RootCid())
213
214 rp, _, err := api.ResolvePath(ctx, p)
215 if err != nil {
216 t.Fatal(err)
217 }
218 if rp.RootCid().String() != res.Path().RootCid().String() {
219 t.Error("paths didn't match")
220 }
221 }
222
223 func (tp *TestSuite) TestBlockRm(t *testing.T) {
224 ctx := t.Context()
225 api, err := tp.makeAPI(t, ctx)
226 if err != nil {
227 t.Fatal(err)
228 }
229
230 res, err := api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Format("raw"))
231 if err != nil {
232 t.Fatal(err)
233 }
234
235 r, err := api.Block().Get(ctx, res.Path())
236 if err != nil {
237 t.Fatal(err)
238 }
239
240 d, err := io.ReadAll(r)
241 if err != nil {
242 t.Fatal(err)
243 }
244
245 if string(d) != "Hello" {
246 t.Error("didn't get correct data back")
247 }
248
249 err = api.Block().Rm(ctx, res.Path())
250 if err != nil {
251 t.Fatal(err)
252 }
253
254 _, err = api.Block().Get(ctx, res.Path())
255 if err == nil {
256 t.Fatal("expected err to exist")
257 }
258 if !ipld.IsNotFound(err) {
259 t.Errorf("unexpected error; %s", err.Error())
260 }
261
262 err = api.Block().Rm(ctx, res.Path())
263 if err == nil {
264 t.Fatal("expected err to exist")
265 }
266 if !ipld.IsNotFound(err) {
267 t.Errorf("unexpected error; %s", err.Error())
268 }
269
270 err = api.Block().Rm(ctx, res.Path(), opt.Block.Force(true))
271 if err != nil {
272 t.Fatal(err)
273 }
274 }
275
276 func (tp *TestSuite) TestBlockStat(t *testing.T) {
277 ctx := t.Context()
278 api, err := tp.makeAPI(t, ctx)
279 if err != nil {
280 t.Fatal(err)
281 }
282
283 res, err := api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Format("raw"))
284 if err != nil {
285 t.Fatal(err)
286 }
287
288 stat, err := api.Block().Stat(ctx, res.Path())
289 if err != nil {
290 t.Fatal(err)
291 }
292
293 if stat.Path().String() != res.Path().String() {
294 t.Error("paths don't match")
295 }
296
297 if stat.Size() != len("Hello") {
298 t.Error("length doesn't match")
299 }
300 }
301
302 func (tp *TestSuite) TestBlockPin(t *testing.T) {
303 ctx := t.Context()
304 api, err := tp.makeAPI(t, ctx)
305 if err != nil {
306 t.Fatal(err)
307 }
308
309 _, err = api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Format("raw"))
310 if err != nil {
311 t.Fatal(err)
312 }
313
314 pinCh := make(chan coreiface.Pin)
315 go func() {
316 err = api.Pin().Ls(ctx, pinCh)
317 }()
318
319 for range pinCh {
320 t.Fatal("expected 0 pins")
321 }
322 if err != nil {
323 t.Fatal(err)
324 }
325
326 res, err := api.Block().Put(
327 ctx,
328 strings.NewReader(`Hello`),
329 opt.Block.Pin(true),
330 opt.Block.Format("raw"),
331 )
332 if err != nil {
333 t.Fatal(err)
334 }
335
336 pins, err := accPins(ctx, api)
337 if err != nil {
338 t.Fatal(err)
339 }
340 if len(pins) != 1 {
341 t.Fatal("expected 1 pin")
342 }
343 if pins[0].Type() != "recursive" {
344 t.Error("expected a recursive pin")
345 }
346 if pins[0].Path().String() != res.Path().String() {
347 t.Error("pin path didn't match")
348 }
349 }