master
go 260 lines 6.08 KB
Raw
1 package tests
2
3 import (
4 "context"
5 "io"
6 "testing"
7 "time"
8
9 "github.com/ipfs/boxo/ipns"
10 "github.com/ipfs/boxo/path"
11 iface "github.com/ipfs/kubo/core/coreiface"
12 "github.com/ipfs/kubo/core/coreiface/options"
13 "github.com/stretchr/testify/require"
14 )
15
16 func (tp *TestSuite) TestRouting(t *testing.T) {
17 tp.hasApi(t, func(api iface.CoreAPI) error {
18 if api.Routing() == nil {
19 return errAPINotImplemented
20 }
21 return nil
22 })
23
24 t.Run("TestRoutingGet", tp.TestRoutingGet)
25 t.Run("TestRoutingPut", tp.TestRoutingPut)
26 t.Run("TestRoutingPutOffline", tp.TestRoutingPutOffline)
27 t.Run("TestRoutingFindPeer", tp.TestRoutingFindPeer)
28 t.Run("TestRoutingFindProviders", tp.TestRoutingFindProviders)
29 t.Run("TestRoutingProvide", tp.TestRoutingProvide)
30 }
31
32 func (tp *TestSuite) testRoutingPublishKey(t *testing.T, ctx context.Context, api iface.CoreAPI, opts ...options.NamePublishOption) (path.Path, ipns.Name) {
33 p, err := addTestObject(ctx, api)
34 require.NoError(t, err)
35
36 name, err := api.Name().Publish(ctx, p, opts...)
37 require.NoError(t, err)
38
39 time.Sleep(3 * time.Second)
40 return p, name
41 }
42
43 func (tp *TestSuite) TestRoutingGet(t *testing.T) {
44 ctx := t.Context()
45
46 apis, err := tp.MakeAPISwarm(t, ctx, 2)
47 require.NoError(t, err)
48
49 // Node 1: publishes an IPNS name
50 p, name := tp.testRoutingPublishKey(t, ctx, apis[0])
51
52 // Node 2: retrieves the best value for the IPNS name.
53 data, err := apis[1].Routing().Get(ctx, ipns.NamespacePrefix+name.String())
54 require.NoError(t, err)
55
56 rec, err := ipns.UnmarshalRecord(data)
57 require.NoError(t, err)
58
59 val, err := rec.Value()
60 require.NoError(t, err)
61 require.Equal(t, p.String(), val.String())
62 }
63
64 func (tp *TestSuite) TestRoutingPut(t *testing.T) {
65 ctx := t.Context()
66 apis, err := tp.MakeAPISwarm(t, ctx, 2)
67 require.NoError(t, err)
68
69 // Create and publish IPNS entry.
70 _, name := tp.testRoutingPublishKey(t, ctx, apis[0])
71
72 // Get valid routing value.
73 data, err := apis[0].Routing().Get(ctx, ipns.NamespacePrefix+name.String())
74 require.NoError(t, err)
75
76 // Put routing value.
77 err = apis[1].Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data)
78 require.NoError(t, err)
79 }
80
81 func (tp *TestSuite) TestRoutingPutOffline(t *testing.T) {
82 ctx := t.Context()
83
84 // init a swarm & publish an IPNS entry to get a valid payload
85 apis, err := tp.MakeAPISwarm(t, ctx, 2)
86 require.NoError(t, err)
87
88 _, name := tp.testRoutingPublishKey(t, ctx, apis[0], options.Name.AllowOffline(true))
89 data, err := apis[0].Routing().Get(ctx, ipns.NamespacePrefix+name.String())
90 require.NoError(t, err)
91
92 // init our offline node and try to put the payload
93 api, err := tp.makeAPIWithIdentityAndOffline(t, ctx)
94 require.NoError(t, err)
95
96 err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data)
97 require.Error(t, err, "this operation should fail because we are offline")
98
99 err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data, options.Routing.AllowOffline(true))
100 require.NoError(t, err)
101 }
102
103 func (tp *TestSuite) TestRoutingFindPeer(t *testing.T) {
104 ctx := t.Context()
105 apis, err := tp.MakeAPISwarm(t, ctx, 5)
106 if err != nil {
107 t.Fatal(err)
108 }
109
110 self0, err := apis[0].Key().Self(ctx)
111 if err != nil {
112 t.Fatal(err)
113 }
114
115 laddrs0, err := apis[0].Swarm().LocalAddrs(ctx)
116 if err != nil {
117 t.Fatal(err)
118 }
119 if len(laddrs0) != 1 {
120 t.Fatal("unexpected number of local addrs")
121 }
122
123 time.Sleep(3 * time.Second)
124
125 pi, err := apis[2].Routing().FindPeer(ctx, self0.ID())
126 if err != nil {
127 t.Fatal(err)
128 }
129
130 if pi.Addrs[0].String() != laddrs0[0].String() {
131 t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
132 }
133
134 self2, err := apis[2].Key().Self(ctx)
135 if err != nil {
136 t.Fatal(err)
137 }
138
139 pi, err = apis[1].Routing().FindPeer(ctx, self2.ID())
140 if err != nil {
141 t.Fatal(err)
142 }
143
144 laddrs2, err := apis[2].Swarm().LocalAddrs(ctx)
145 if err != nil {
146 t.Fatal(err)
147 }
148 if len(laddrs2) != 1 {
149 t.Fatal("unexpected number of local addrs")
150 }
151
152 if pi.Addrs[0].String() != laddrs2[0].String() {
153 t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
154 }
155 }
156
157 func (tp *TestSuite) TestRoutingFindProviders(t *testing.T) {
158 ctx := t.Context()
159 apis, err := tp.MakeAPISwarm(t, ctx, 5)
160 if err != nil {
161 t.Fatal(err)
162 }
163
164 p, err := addTestObject(ctx, apis[0])
165 if err != nil {
166 t.Fatal(err)
167 }
168
169 // Pin so that it is provided, given that providing strategy is
170 // "roots" and addTestObject does not pin.
171 err = apis[0].Pin().Add(ctx, p)
172 if err != nil {
173 t.Fatal(err)
174 }
175
176 time.Sleep(3 * time.Second)
177
178 out, err := apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
179 if err != nil {
180 t.Fatal(err)
181 }
182
183 provider := <-out
184
185 self0, err := apis[0].Key().Self(ctx)
186 if err != nil {
187 t.Fatal(err)
188 }
189
190 if provider.ID.String() != self0.ID().String() {
191 t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
192 }
193 }
194
195 func (tp *TestSuite) TestRoutingProvide(t *testing.T) {
196 ctx := t.Context()
197 apis, err := tp.MakeAPISwarm(t, ctx, 5)
198 if err != nil {
199 t.Fatal(err)
200 }
201
202 off0, err := apis[0].WithOptions(options.Api.Offline(true))
203 if err != nil {
204 t.Fatal(err)
205 }
206
207 s, err := off0.Block().Put(ctx, &io.LimitedReader{R: rnd, N: 4092})
208 if err != nil {
209 t.Fatal(err)
210 }
211
212 p := s.Path()
213
214 time.Sleep(3 * time.Second)
215
216 out, err := apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
217 if err != nil {
218 t.Fatal(err)
219 }
220
221 _, ok := <-out
222
223 if ok {
224 t.Fatal("did not expect to find any providers")
225 }
226
227 self0, err := apis[0].Key().Self(ctx)
228 if err != nil {
229 t.Fatal(err)
230 }
231
232 err = apis[0].Routing().Provide(ctx, p)
233 if err != nil {
234 t.Fatal(err)
235 }
236
237 maxAttempts := 5
238 success := false
239 for range maxAttempts {
240 // We may need to try again as Provide() doesn't block until the CID is
241 // actually provided.
242 out, err = apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
243 if err != nil {
244 t.Fatal(err)
245 }
246 provider := <-out
247
248 if provider.ID.String() == self0.ID().String() {
249 success = true
250 break
251 }
252 if len(provider.ID.String()) > 0 {
253 t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
254 }
255 time.Sleep(time.Second)
256 }
257 if !success {
258 t.Errorf("missing provider after %d attempts", maxAttempts)
259 }
260 }