@cryptotaxi247 / kubo / commits / 635a5c798

integration test for the dual dht

Will Scott committed Apr 13, 2020 at 17:10 UTC 635a5c798eb3d2b3468fbd7004f93865b1527eae
1 file changed +223
test/integration/wan_lan_dht_test.go new
+223
@@ -0,0 +1,223 @@
1 +package integrationtest
2 +
3 +import (
4 + "context"
5 + "encoding/binary"
6 + "fmt"
7 + "math"
8 + "math/rand"
9 + "net"
10 + "testing"
11 + "time"
12 +
13 + "github.com/ipfs/go-cid"
14 + "github.com/ipfs/go-ipfs/core"
15 + "github.com/ipfs/go-ipfs/core/bootstrap"
16 + mock "github.com/ipfs/go-ipfs/core/mock"
17 +
18 + corenet "github.com/libp2p/go-libp2p-core/network"
19 + peer "github.com/libp2p/go-libp2p-core/peer"
20 + "github.com/libp2p/go-libp2p-core/peerstore"
21 + testutil "github.com/libp2p/go-libp2p-testing/net"
22 + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
23 +
24 + ma "github.com/multiformats/go-multiaddr"
25 +)
26 +
27 +func TestDHTConnectivityFast(t *testing.T) {
28 + conf := testutil.LatencyConfig{
29 + NetworkLatency: 0,
30 + RoutingLatency: 0,
31 + BlockstoreLatency: 0,
32 + }
33 + if err := RunDHTConnectivity(conf, 5); err != nil {
34 + t.Fatal(err)
35 + }
36 +}
37 +
38 +func TestDHTConnectivitySlowNetwork(t *testing.T) {
39 + SkipUnlessEpic(t)
40 + conf := testutil.LatencyConfig{NetworkLatency: 400 * time.Millisecond}
41 + if err := RunDHTConnectivity(conf, 5); err != nil {
42 + t.Fatal(err)
43 + }
44 +}
45 +
46 +func TestDHTConnectivitySlowRouting(t *testing.T) {
47 + SkipUnlessEpic(t)
48 + conf := testutil.LatencyConfig{RoutingLatency: 400 * time.Millisecond}
49 + if err := RunDHTConnectivity(conf, 5); err != nil {
50 + t.Fatal(err)
51 + }
52 +}
53 +
54 +var wanPrefix = net.ParseIP("100::")
55 +var lanPrefix = net.ParseIP("fe80::")
56 +
57 +func makeAddr(n uint32, wan bool) ma.Multiaddr {
58 + var ip net.IP
59 + if wan {
60 + ip = append(net.IP{}, wanPrefix...)
61 + } else {
62 + ip = append(net.IP{}, lanPrefix...)
63 + }
64 +
65 + binary.LittleEndian.PutUint32(ip[4:], n)
66 + addr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/4242", ip))
67 + return addr
68 +}
69 +
70 +func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error {
71 + ctx, cancel := context.WithCancel(context.Background())
72 + defer cancel()
73 +
74 + // create network
75 + mn := mocknet.New(ctx)
76 + mn.SetLinkDefaults(mocknet.LinkOptions{
77 + Latency: conf.NetworkLatency,
78 + Bandwidth: math.MaxInt32,
79 + })
80 +
81 + testPeer, err := core.NewNode(ctx, &core.BuildCfg{
82 + Online: true,
83 + Host: mock.MockHostOption(mn),
84 + })
85 + if err != nil {
86 + return err
87 + }
88 + defer testPeer.Close()
89 +
90 + wanPeers := []*core.IpfsNode{}
91 + lanPeers := []*core.IpfsNode{}
92 +
93 + for i := 0; i < numPeers; i++ {
94 + wanPeer, err := core.NewNode(ctx, &core.BuildCfg{
95 + Online: true,
96 + Host: mock.MockHostOption(mn),
97 + })
98 + if err != nil {
99 + return err
100 + }
101 + defer wanPeer.Close()
102 + wanAddr := makeAddr(uint32(i), true)
103 + wanPeer.Peerstore.AddAddr(wanPeer.Identity, wanAddr, peerstore.PermanentAddrTTL)
104 + for _, p := range wanPeers {
105 + mn.ConnectPeers(p.Identity, wanPeer.Identity)
106 + }
107 + wanPeers = append(wanPeers, wanPeer)
108 +
109 + lanPeer, err := core.NewNode(ctx, &core.BuildCfg{
110 + Online: true,
111 + Host: mock.MockHostOption(mn),
112 + })
113 + if err != nil {
114 + return err
115 + }
116 + defer lanPeer.Close()
117 + lanAddr := makeAddr(uint32(i), false)
118 + lanPeer.Peerstore.AddAddr(lanPeer.Identity, lanAddr, peerstore.PermanentAddrTTL)
119 + for _, p := range lanPeers {
120 + mn.ConnectPeers(p.Identity, lanPeer.Identity)
121 + }
122 + lanPeers = append(lanPeers, lanPeer)
123 + }
124 +
125 + // The test peer is connected to one lan peer.
126 + _, err = mn.ConnectPeers(testPeer.Identity, lanPeers[0].Identity)
127 + if err != nil {
128 + return err
129 + }
130 +
131 + err, done := <-testPeer.DHT.RefreshRoutingTable()
132 + if err != nil || !done {
133 + if !done {
134 + err = fmt.Errorf("expected refresh routing table to close")
135 + }
136 + return err
137 + }
138 +
139 + // choose a lan peer and validate lan DHT is functioning.
140 + i := rand.Intn(len(lanPeers))
141 + if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected {
142 + testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity)
143 + testPeer.PeerHost.Peerstore().ClearAddrs(lanPeers[i].Identity)
144 + }
145 + // That peer will provide a new CID, and we'll validate the test node can find it.
146 + provideCid := cid.NewCidV1(cid.Raw, []byte("Lan Provide Record"))
147 + provideCtx, cancel := context.WithTimeout(ctx, time.Second)
148 + defer cancel()
149 + if err := lanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil {
150 + return err
151 + }
152 + provs, err := testPeer.DHT.FindProviders(provideCtx, provideCid)
153 + if err != nil {
154 + return err
155 + }
156 + if len(provs) != 1 {
157 + return fmt.Errorf("Expected one provider, got %d", len(provs))
158 + }
159 + if provs[0].ID != lanPeers[i].Identity {
160 + return fmt.Errorf("Unexpected lan peer provided record")
161 + }
162 +
163 + // Now, bootstrap from a wan peer.
164 + bis := wanPeers[0].Peerstore.PeerInfo(wanPeers[0].PeerHost.ID())
165 + bcfg := bootstrap.BootstrapConfigWithPeers([]peer.AddrInfo{bis})
166 + if err := testPeer.Bootstrap(bcfg); err != nil {
167 + return err
168 + }
169 +
170 + err, done = <-testPeer.DHT.RefreshRoutingTable()
171 + if err != nil || !done {
172 + if !done {
173 + err = fmt.Errorf("expected refresh routing table to close")
174 + }
175 + return err
176 + }
177 +
178 + // choose a wan peer and validate wan DHT is functioning.
179 + i = rand.Intn(len(wanPeers))
180 + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected {
181 + testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity)
182 + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity)
183 + }
184 + // That peer will provide a new CID, and we'll validate the test node can find it.
185 + wanCid := cid.NewCidV1(cid.Raw, []byte("Wan Provide Record"))
186 + wanProvideCtx, cancel := context.WithTimeout(ctx, time.Second)
187 + defer cancel()
188 + if err := wanPeers[i].DHT.Provide(wanProvideCtx, wanCid, true); err != nil {
189 + return err
190 + }
191 + provs, err = testPeer.DHT.FindProviders(wanProvideCtx, wanCid)
192 + if err != nil {
193 + return err
194 + }
195 + if len(provs) != 1 {
196 + return fmt.Errorf("Expected one provider, got %d", len(provs))
197 + }
198 + if provs[0].ID != wanPeers[i].Identity {
199 + return fmt.Errorf("Unexpected lan peer provided record")
200 + }
201 +
202 + // Finally, re-share the lan provided cid from a wan peer and expect a merged result.
203 + i = rand.Intn(len(wanPeers))
204 + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected {
205 + testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity)
206 + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity)
207 + }
208 +
209 + provideCtx, cancel = context.WithTimeout(ctx, time.Second)
210 + defer cancel()
211 + if err := wanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil {
212 + return err
213 + }
214 + provs, err = testPeer.DHT.FindProviders(provideCtx, provideCid)
215 + if err != nil {
216 + return err
217 + }
218 + if len(provs) != 2 {
219 + return fmt.Errorf("Expected two providers, got %d", len(provs))
220 + }
221 +
222 + return nil
223 +}