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
+}